Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a Javascript array based on every other element

Assume that I have an array like so:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];

Even-numbered array indices are linked with the following odd index. In other words, 94 goes with "Neputunium" and 2 goes with "Helium" etc. How can I sort the array based on the even-numbered indices but keep the following odd-indexed value after it? So that I end up with an array like so:

a = [null, "Hypotheticalium", 2, "Helium", 64, "Promethium", 94, "Neptunium"];

NOTE: And yes, I do know that know that using an object or ES6 Map (or even, in this case, a sparse array with the numbers as indices, if null is left out) would be much more appropriate, but I'm just exploring this to experiment with the language. Thanks for any help.

like image 989
user162097 Avatar asked Sep 30 '15 07:09

user162097


People also ask

How do you sort an array of objects in JavaScript based on another array?

const arr1 = ['d','a','b','c'] ; const arr2 = [{a:1},{c:3},{d:4},{b:2}]; We are required to write a JavaScript function that accepts these two arrays. The function should sort the second array according to the elements of the first array.

How do you sort an array based on another array?

Method 1 (Using Sorting and Binary Search)Create a temporary array temp of size m and copy the contents of A1[] to it. Create another array visited[] and initialize all entries in it as false. visited[] is used to mark those elements in temp[] which are copied to A1[]. Initialize the output index ind as 0.

How do you sort an array with two elements?

Step 1 : Here we can take two pointers type0 (for element 0) starting from beginning (index = 0) and type1 (for element 1) starting from end index. Step 2: We intend to put 1 to the right side of the array. Once we have done this then 0 will definitely towards left side of array to achieve this we do following.


3 Answers

Since the order of the calls to sort is not necessarily the same one JavaScript engine to the next (or even between revs of the same engine), you can't use sort directly on that array to do what you've described.

You can use map, filter, sort, then reduce however:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
  .map(function(entry, index, array) {
    return (index % 2 === 1) ? null : {
      value: array[index + 1],
      index: entry
    };
  })
  .filter(function(entry) {
    return entry != null;
  })
  .sort(function(left, right) {
    return left.index - right.index; // Works even when either or both
                                     // indexes are null, PROVIDED
                                     // no non-null index is negative,
                                     // because `null` will coerce to 0
  })
  .reduce(function(acc, entry) {
    acc.push(entry.index, entry.value);
    return acc;
  }, []);
document.body.innerHTML = JSON.stringify(a);

The map lets us produce an array with objects for the paired entries (and nulls).

The filter lets us remove the nulls.

The sort lets us sort.

The reduce lets us produce an array of the results (since we can't use map directly to map one entry to two).

If you may have negative values for your even-numbered entries, the sort callback has to handle things differently because it will sort null above those negative indexes (unless of course that's what you want).


It's a bit more concise in ES6: (live on Babel's REPL)

let a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
  .map((entry, index, array) => {
    return (index % 2 === 1) ? null : {
      value: array[index + 1],
      index: entry
    };
  })
  .filter(entry => entry != null)
  .sort((left, right) => left.index - right.index)
  .reduce((acc, entry) => {
    acc.push(entry.index, entry.value);
    return acc;
  }, []);
console.log(a);
like image 87
T.J. Crowder Avatar answered Oct 14 '22 19:10

T.J. Crowder


var grouped = [];
for (var i = 0; i < a.length; i += 2) {
    grouped.push([a[i], a[i+1]]);
}

grouped.sort(function (a, b) { return a[0] - b[0]; });

Ideally I'd suggest you use the grouped structure from here on, since it seems to make more sense to group grouped items together, instead of relying on implicit adjacent indices. But if you need to unpack it again:

var b = [];
for (var i = 0; i < grouped.length; i++) {
    b.push.apply(b, grouped[i]);
}
like image 34
deceze Avatar answered Oct 14 '22 19:10

deceze


You need some grouping and appropriate sorting and reorganization of the array.

var array = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"],
    sorted = array.reduce(function (r, a, i) {
        i % 2 ? r[r.length - 1].push(a) : r.push([a]);
        return r;
    }, []).sort(function (a, b) {
        return a[0] - b[0];
    }).reduce(function (r, a) {
        return r.concat(a);
    });
document.write('<pre>' + JSON.stringify(sorted, 0, 4) + '</pre>');
like image 26
Nina Scholz Avatar answered Oct 14 '22 21:10

Nina Scholz