Sort Javascript array based on any other element

Suppose I have an array like this:

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

The indices of even-numbered arrays are associated with the following odd index. In other words, 94 comes with Neputunium and 2 comes with Helium, etc. How can I sort an array based on indices with even numbers, but after it save the next odd value? So I get an array like this:

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

NOTE: And yes, I know that I know that using an ES6 object or map (or even in this case a sparse array with index numbers if null is not specified) would be much more appropriate, but I just study this, to experiment with the language. Thanks for any help.

+4
source share
4 answers

Since the order of calls is sortnot necessarily the same JavaScript engine for the next (or even between the revolutions of the same engine), you cannot sortdirectly use this array to do what you described.

You can use the map, filter, sort, and then reduce:

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);
Run codeHide result

mapallows us to create an array with objects for paired records (and nulls).

filterallows you to remove nulls.

sort allows you to sort.

reduceallows us to create an array of results (since we cannot use mapdirectly to match one record with two).

, sort , null (, , , ).


ES6: ( Babel 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);
+3
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]; });

grouped , , , . :

var b = [];
for (var i = 0; i < grouped.length; i++) {
    b.push.apply(b, grouped[i]);
}
+5

.

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>');
Hide result
+1

, JS, , , sort gnome sort:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
for (var i = 0, temp; i < a.length; i += 2) {
    if (a[i] > a[i + 2]) {
        temp = a[i];
        a[i] = a[i + 2];
        a[i + 2] = temp;
        temp = a[i + 1];
        a[i + 1] = a[i + 3];
        a[i + 3] = temp;
        i = i - 4;
    }
}
alert(JSON.stringify(a));

Of course, this is not the fastest sorting algorithm, but just a proof of concept to show that this can be done without changing my structure and without a lot of (potentially expensive) function calls (although I agree that functional programming is more of a JS idiom). And I could put the swap code in my own function with two calls, for DRY's sake , for example:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
function arraySwapper(array, index1, index2) {
    var temp = array[index1];
    array[index1] = array[index2], array[index2] = temp;
}
for (var i = 0, j; i < a.length; i += 2) {
    if (a[i] > a[i + 2]) {
        for (j = i; j < i + 2; j++) { arraySwapper(a, j, j + 2); }
        i -= 4;
    }
}
alert(JSON.stringify(a));
Run codeHide result
0
source

Source: https://habr.com/ru/post/1609576/


All Articles