gordyr
gordyr

Reputation: 6276

Reordering an array in javascript

there are many questions/answers dealing with this topic. None match my specific case. Hopefully someone can help:

I have an array of indexes such as:

var indexes = [24, 48, 32, 7, 11];

And an array of objects that look similar to this:

var items = [{
              name : "whatever",
              selected : false,
              loading : true,
              progress : 55,
              complete : false
},
{
              name : "whatever 2",
              selected : false,
              loading : false,
              progress : 100,
              complete : true
}];

Each integer within the indexes array corresponds to the actual index of an object within the items array.

Lastly I have a variable which defines the new insert position within the items array:

 var insertindex = ??

What I would like to do is to take all objects in the items array that have the indexes stored in the indexes array, remove them, then finally place them back, all next to each other at a specified index defined by the variable insertindex.

I have been trying to use splice() by copying the objects at each index to a temporary array, then removing them from the original array, then finally looping through this new temporary array and putting them back into the original items array at the new positions, but seems to be hitting a mental brick wall and cannot get it to work correctly.

To summarize, I simply want to take all objects from the items array that match an index defined in the indexes array, put them together and reinsert them at a predefined index, back into the items array.

To help with conceptual visualization. If you think of the app as a javascript file manager, allowing the reordering of multiple file selections which do not have to be adjacent. The indexes array defining the current selection and the items array defining the list of files. And finally the rearoderindex defines the new insert position that all selected files should move to.

EDIT: As was rightly suggested here is the code I am playing with right now:

function reorder(items, indexes, insertindex){

        var offset = 0;
        var itemscopy = items.slice(0); //make shallow copy of original array
        var temparray = new Array(); // create temporary array to hold pulled out objects

        //loop through selected indexes and copy each into temp array
        for(var i=0, len=indexes.length; i<len; i++){ 
            array[i] = itemscopy[self.cache.selecteditems[i]];
        }


        //remove all selected items from items array
        for(var i=0, len=indexes.length; i<len; i++){
            items.splice(indexes[i], 1);
        }

        //finally loop through new temp array and insert the items back into the items array at the specified index, increasing the index each iteration using the offset variable.
        for(var i=0, len=temparray.length; i<len; i++){
            items.splice((insertindex+offset), 0, array[i]);
            offset++;
        }

}

I'm aware this is pretty horrible and that looping three times should not be necessary. But I've been trying lots of different methods, some working when reordering in one direction, some in the other an mostly, not at all. I figured I would look to optimize the function later, once I have it working with accuracy.

I'm certain I must be doing something extremely stupid or completely overlooking something, but for the life of me I can't work out what right now.

Upvotes: 4

Views: 9953

Answers (2)

VisioN
VisioN

Reputation: 145368

If you don't care about order of indexes array, I'd suggest another short solution:

items.splice.apply(items, [insertIndex, 0].concat(indexes.sort(function(a, b) {
    return a - b;
})).map(function(i, p) {
    return p > 1 ? items.splice(i - p + 2, 1).pop() : i;
}));

DEMO: http://jsfiddle.net/T83fB/

To make it short I used Array.map() method, which is not supported by old IE browsers. However it is always easy to use a shim from MDN.

Upvotes: 5

Anthony Grist
Anthony Grist

Reputation: 38345

You can use the .splice() function to add elements to an array, as well as removing items from it. The general principle is:

  1. Sort indexes into ascending numeric order
  2. Iterate over indexes, removing the element at that index (adjusting for the number of removed items) and storing it in a removedItems array
  3. Add the removedItems array back in at the required index

The code to do that would look something like this:

var removedItems = [];
// sort indexes
indexes.sort(function(a, b) {
    if(a < b) return -1;
    else if(b < a) return 1;
    return 0;
});
for(var i = 0; i < indexes.length; i++) {
    var index = indexes[i];
    removedItems.push(items.splice(index - removedItems.length, 1));
}
var insertIndex = 1;
items.splice.apply(items, [insertIndex, 0].concat(removedItems));

Take a look at this jsFiddle demo.

Upvotes: 2

Related Questions