What is the best way to partially organize an array according to a specific condition?

Is there a way to partially sort an array in JavaScript based on specific conditions I choose?

Let's say we have an array:

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and many more items...
];

In this array, the 2nd item is marked as "locked" and should remain at the same position (2nd place) after sorting:

var tab = [
    {html: 'Another item'},
    {html: 'Locked item', locked: true},
    {html: 'Another one'},
    {html: 'This is a test'},
    //and many more items...
];

This is the current code snippet that needs modification:

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and more items...
];

tab.sort(function(a,b){
    var aVal = a.html.toLowerCase();
    var bVal = b.html.toLowerCase();
    if (aVal===bVal)
        return 0;
    else
        return aVal < bVal ? -1 : 1;

    //how can we handle locked items here?
});

//desired output:
/*var tab = [
    {html: 'Another item'},
    {html: 'Locked item', locked: true},
    {html: 'Another one'},
    {html: 'This is a test'},
    //and more items...
];*/

console.log(tab);

For reference, you can check the fiddle.

Answer №1

The issue at hand is the misuse of sort for linear sorting purposes only. Utilizing it beyond its intended functionality can lead to unreliable results, especially considering potential browser optimizations that may affect its execution.

Therefore, the solution lies in selectively applying linear sorting to specific sections of your array. The recommended approach involves extracting and storing the locked elements along with their respective indexes, performing the sort operation, and then reinserting the locked elements back into their original positions within the array.

var fixed = [], i;
for (i = tab.length; i--;) {
    if (tab[i].locked) {
        fixed.unshift({index: i, item: tab[i]});
        tab.splice(i, 1);
    }
}

tab.sort(...); // Implement your sorting logic here

for (i = 0; i < fixed.length; i++)
    tab.splice(fixed[i].index, 0, fixed[i].item);

It's important not to be confused by the utilization of a reverse for loop and the use of unshift instead of push. These choices are made to preserve the correct indexing structure.

The backward looping strategy compensates for the array modifications caused by splice, ensuring no items are skipped during the process. This method also maintains the sorting order of the fixed array based on the index property.

Keep in mind that while splice may be effective for small arrays with only a few fixed elements, it can be inefficient for larger datasets. In such cases, consider utilizing more optimized algorithms for improved performance.

Answer №2

This method shows some promise:

tab.sort(function(a,b){
    if(a.locked || b.locked)
        return 0;
    if (a.html < b.html)
        return -1;
    if (a.html > b.html)
        return 1;
    return 0;
});

The issue lies in its inability to properly position the first item after a locked item due to constraints within the sorting algorithm utilized by sort. Despite this, it effectively sorts groups of two or more items as shown in your specific instance.

To accomplish your desired outcome, consider extracting the locked elements from the array, recording their indices in a variable, performing the sort on the remaining array, and finally reintegrating the locked elements into their original positions.

Answer №3

To potentially improve efficiency, one approach could involve removing all locked items from an array, storing their original positions, sorting the remaining items, and then reintroducing the locked items back into the sorted array:

var tab = [
    {html: 'This is a test'},
    {html: 'Locked item', locked: true},
    {html: 'Another item'},
    {html: 'Another one'}
    //and more items...
];

var stored = {}, newTab = [];
for(var i = 0, iLimit = tab.length; i < iLimit; i++) {
    if(tab[i].locked) {
        stored[i] = tab[i];
    } else {
        newTab.push(tab[i]);
    }
}

newTab.sort(function(a,b){
    var aVal = a.html.toLowerCase();
    var bVal = b.html.toLowerCase();
    if (aVal===bVal) {
        return 0;
    } else {
        return aVal < bVal ? -1 : 1;
    }
});

for(var indice in stored) {
    newTab.splice(indice, 0, stored[indice]);
}

console.log(newTab);

http://jsfiddle.net/qW7uH/2/

Answer №4

Another approach could be to eliminate all the locked items and store them in a separate array as shown below:

[
    { obj: ..., index: ...}, 
    { ... }
] 

This method preserves the index for each object. You can then insert them back after sorting, although it may seem a bit cumbersome.

Refer to Array.prototype.filter for filtering, but keep in mind that it may not function properly in IE8 without a polyfill.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The website becomes unresponsive and locks up after being on the same page for several

We are dealing with a PHP web application that heavily utilizes javascript and jquery. The main issue we are facing involves a create/read/update/delete page where users can modify content. These modifications occur using AJAX, which prevents a full page r ...

Starting objects before utilizing them in the useFrame() function in react-three-fiber

I am currently working on a project using react-three-fiber to create a scene. However, I am facing an issue with placing 3D objects at different random positions. I tried using a for loop inside useFrame to set random positions, but this causes the partic ...

Unable to dynamically attach a class in Vue.js

I have exhausted all possible variations of this issue. I meticulously followed the official Vue guides, consulted numerous stack overflow posts, and went through various tutorials. I experimented with different syntaxes, quotations, array structures, and ...

A guide on retrieving values from programmatically created input elements in Java

Here's the HTML code that I am currently working with: <form method="get" action="#" id="startForm"> <input type="text" name="period" id="period" placeholder="The number of days"/> <input type="submit" name="submit" value="subm ...

Secure login verification coupled with intuitive navigation features

Just starting out with react native and I've created a UI for a restaurant app. Now I'm working on converting all static components to dynamic ones. My first task is figuring out how to implement login authentication and then navigate to a specif ...

After implementing ajax, jQuery ceases to function

I have been working with multiple JavaScript files and everything is functioning perfectly (including functions that add styles to elements), but I am encountering an issue when trying to include the following script: <script src="http://ajax.googleapi ...

Ways to prevent a specific class from using CSS styling

My HTML <body> <div id="finalparent"> <!--many parent divs here--> <div id="1stparent"> <div id="txt_blog_editor" class="box" style="width: 1097px;"> <div class="abc anotherclass"> </div> & ...

Setting up nunjucks for using custom filters with express

My attempt to implement a custom filter with nunjucks, as per the documentation, resulted in an error message: Error: filter not found: my_filter_here Here are the configurations I have: index.js const express = require('express'); const nunjuc ...

What is the most effective method for handling extremely large Long numbers in Ajax?

When it comes to Javascript, all numbers are represented as double-precision floating-point. This can result in a loss of precision when handling numbers that exceed the 64 bit Java Long datatype limit of 17 digits. For instance, a number like: 7143412520 ...

Exporting JSON data as an Excel file in AngularJS, including the option to customize the fonts used for the

Currently, I am working on a project where I need to convert JSON data to an Excel file using JavaScript in combination with AngularJS. So far, I have successfully converted the JSON data to CSV format. However, I faced issues with maintaining the font s ...

Can the color of text be adjusted (to either white or black) based on the background color (in any color and format)?

To achieve a text color that contrasts well with any background, I need to make sure it's either black or white. The background in my app can vary in color and format, so finding the perfect solution has been challenging. Using mix-blend-mode doesn&a ...

Specialized selection option with disabled function

Looking for assistance with a script to create a custom select box. I have UL and LI elements overlapping a select element, but I want to prevent the UL LI from opening when the select has a "disabled" attribute. Can anyone provide guidance on how to achie ...

Showing JSON information fetched from an AJAX request within an HTML page

I've been working on a project and I'm almost there with everything figured out. My main challenge now is to display an array of items on a web page after making an ajax call. Below is the code snippet I currently have: JQuery Code: var su ...

Issue with Route Transition in React Router version 4 when using Styled Components

I am currently in the process of constructing a React Application utilizing React-Router@4, <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b5e7d0d4d6c198fddac198f9dad4d1d0c7f5869bd7d0c1d49b83">[email protected]</a> ...

Fixing a menu hover appearance

I recently encountered a small issue with the menu on my website. When hovering over a menu item, a sub-menu should appear. However, there seems to be a slight misalignment where the submenu appears a few pixels below the actual menu item. Check out the w ...

Interrogating a multi-dimensional array using the MongoDB C# driver

Here is how my document is structured: "ID" : "fruit1", "Keys" : [ ["apple", "carrot"] ["banana"] ] I am trying to query for Keys = "carrot" using MongoDB C# driver. Can anyone help with this? When I tried in shell, this ...

Removing the gap between the clicked point and the draw point in Html5 canvas

To better understand my issue, please refer to the image linked below: In the image, you can see that when I scroll down and click on the canvas to point a position, it creates space between the clicked point and where the line is drawn. Below is the cod ...

Here are the steps to organize a Collection containing generic Pair elements

I am seeking help with my homework and would appreciate an explanation rather than just receiving the answer outright. In my assignment, I have developed a versatile Pair class that is able to accept any key value represented by K, and any value represent ...

What is the best method for determining the cookie expiration time in AngularJS 1.3?

Currently in my application, I am utilizing AngularJS 1.3. I encountered a challenge while using $cookies to store data where I needed to implement a 1-minute expiration time for the cookie. However, the $cookies service in AngularJS 1.3 does not provide ...

Typescript encounters ERROR TS1128: Expecting a declaration or statement

Having trouble with a TypeScript error in my game-details.component.ts file that I've been trying to fix for a couple of hours. It's showing up at line 26, column 54 and everything seems correct to me. Interestingly, when I press CTRL + S in my ...