0

I have an array that looks like:

[
  ["A","B","C","D"],
  ["E","F","G","H"],
  [6,43,2,4]
]

I want to sort this array in descending order of the items in the third row, such that it looks like:

[
  ["B","A","D","C"],
  ["F","E","H","G"],
  [43,6,4,2]
]

So far this is what I wrote:

var arr = [
  ["A","B","C","D"],
  ["E","F","G","H"],
  [6,43,2,4]
]

arr = arr.sort((a,b) => {
  return b[2] - a[2]
});

console.log(arr);

But the array does not get sorted. Where did I go wrong?

Wais Kamal
  • 5,858
  • 2
  • 17
  • 36
  • 1
    Do you want to sort the array or the subarrays? If the latter, then you should map a sorting function over the overall array – John Coleman Feb 14 '19 at 16:37
  • Do you only want to sort the third nested array? What about the sorting for the other two? – Tom O. Feb 14 '19 at 16:37
  • I want to sort the subarrays by the values in the third array. – Wais Kamal Feb 14 '19 at 16:39
  • @TomO. as you can see in the test case, the corresponding elements in the other arrays should also get sorted. – Wais Kamal Feb 14 '19 at 16:39
  • You're problem comes from the fact you sort the "super" array when you do arr.sort... You'll have to sort each array with something like (arr[i].sort(...) – Mohicane Feb 14 '19 at 16:43
  • `["A","B","C","D"]` how come this change to this order `["B","A","D","C"]` ? – Code Maniac Feb 14 '19 at 16:44
  • He wants to sort according to the third array result sorting, that is, map the keys from the third array to the other arrays keys. For example, `43` is the position 1 and also `B` and `F`. After sorting them, `43` goes to the position 0 and also `B` and `F` on their arrays. – herodrigues Feb 14 '19 at 16:45
  • @Mulli imagine the array is a table with rows (B,F,43), (A,E,6), ... Sort this table by the values in the last column. – Wais Kamal Feb 14 '19 at 16:45
  • Yeah - what @CodeManiac said - what type of sorting is that for the first two arrays? It's not descending – Tom O. Feb 14 '19 at 16:47
  • Forgive my ignorance of array.sort, but shouldn't you return a bool, not a value? In other words, b[2] < a[2] instead of b[2] - a[2]? –  Feb 14 '19 at 16:47
  • @WaisKamal Are you trying to sort the differences between a and b? – Mulli Feb 14 '19 at 16:48
  • 1
    @Chipster Nope, that is correct - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort – Tom O. Feb 14 '19 at 16:48
  • @TomO. I don't want to sort each array individually. Sort the last array, then place the corresponding elements in that order. – Wais Kamal Feb 14 '19 at 16:48
  • @WaisKamal But my point is that the function defined in sort() is expecting you to return a bool. The function is supposed to be a test as to whether a should come before b in the sorted order. –  Feb 14 '19 at 16:51
  • @WaisKamal So you want first the sort the last array - lets call it the "differences" between a and b. The problem is the there is no guarantee that a and b will have the correct elements. And if they do, its more of a placement and not sorting problem. Am I correct? – Mulli Feb 14 '19 at 16:52
  • @Chipster, [`Array#sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) needs a numerical value, depending on the result of order. – Nina Scholz Feb 14 '19 at 16:52
  • @NinaScholz How do you figure that –  Feb 14 '19 at 16:55
  • @Chipster you need to read the documentation Nina posted – Tom O. Feb 17 '19 at 22:45

4 Answers4

3

You could take the indices of the array for sorting, sort this array by the values of the original array and map all reordered items.

var array = [["A", "B", "C", "D"], ["E", "F", "G", "H"], [6, 43, 2, 4]],
    indices = [...array[2].keys()].sort((a, b) => array[2][b] - array[2][a]);

array = array.map(a => indices.map(i => a[i]));

console.log(array.map(a => a.join(' ')));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
2

You need to first sort the number store indexes and then sort the other arrays.

var arr = [
  ["A","B","C","D"],
  ["E","F","G","H"],
  [6,43,2,4]
]

var tmp = arr[2].map((value, i) => ({value, i})).sort((a, b) => b.value - a.value);

arr = arr.map(function(arr) {
  return tmp.map(({value, i}) => arr[i]);
});

console.log(arr);
jcubic
  • 61,973
  • 54
  • 229
  • 402
2

You want to sort columns. It is easier to sort rows. So, you could transpose then sort then retranspose:

const arr = [
  ["A","B","C","D"],
  ["E","F","G","H"],
  [6,43,2,4]
];

const transpose = array => array[0].map((col, i) => array.map(row => row[i]));

const t = transpose(arr);
t.sort((rowi,rowj) => (rowj[rowj.length - 1] - rowi[rowi.length-1]));
console.log(transpose(t));

Which has the intended output of:

[ [ 'B', 'A', 'D', 'C' ],
  [ 'F', 'E', 'H', 'G' ],
  [ 43, 6, 4, 2 ] ]

This is clearly not as efficient as the other answers, but the fact that you are asking the question suggests that your current way of storing the data isn't convenient for your purposes. Perhaps you might want to transpose then skip the retranspose part.

John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • Thanks! Actually I would prefer the transposed one, but unfortunately that's the way I'm receiving the data. – Wais Kamal Feb 14 '19 at 18:48
1

It would be easier if you could depict the data differently. The Array.sort function will not help you with your current example.

var arr = [{
    a: "A", b: "E", c: 6
},{
    a: "B", b: "F", c: 43
},{
    a: "C", b: "G", c: 2
},{
    a: "D", b: "H", c: 4
}]

arr.sort((a, b) => {
    return b.c - a.c;
})

console.log(arr);

If you can't, I could provide a different answer; but the answer would be very inefficient.

David Kirk
  • 342
  • 3
  • 5