3

I have an object like this in JavaScript:

myArray[0] -> 0:"62", 1:8, 2:0, 3:"11"
myArray[1] -> 0:"62", 1:8, 2:0, 3:"15"
myArray[2] -> 0:"48", 1:8, 2:0, 3:"04"
myArray[3] -> 0:"48", 1:8, 2:0, 3:"01"
myArray[4] -> 0:"62", 1:8, 2:0, 3:"12"
myArray[5] -> 0:"48", 1:8, 2:0, 3:"02"
myArray[6] -> 0:"62", 1:8, 2:0, 3:"14"
myArray[7] -> 0:"48", 1:8, 2:0, 3:"03"

And I'm trying to make it to be like this:

myArray[0] -> 0:"48", 1:8, 2:0, 3:"01"
myArray[1] -> 0:"48", 1:8, 2:0, 3:"02"
myArray[2] -> 0:"48", 1:8, 2:0, 3:"03"
myArray[3] -> 0:"48", 1:8, 2:0, 3:"04"
myArray[4] -> 0:"62", 1:8, 2:0, 3:"11"
myArray[5] -> 0:"62", 1:8, 2:0, 3:"12"
myArray[6] -> 0:"62", 1:8, 2:0, 3:"14"
myArray[7] -> 0:"62", 1:8, 2:0, 3:"15"

As you see, I'm trying to sort it by myArray[i][0] at first, and then sort by myArray[i][3] based on the myArray[i][0] as index. I managed to sort by myArray[i][0] using

myObject.sort(function(a, b){ 
    return parseInt(a) - parseInt(b); 
});

How do I accomplish this with no libraries?

linuxdan
  • 4,476
  • 4
  • 30
  • 41
Pablo
  • 510
  • 8
  • 22
  • 1
    Try looking at this question - http://stackoverflow.com/questions/6913512/how-to-sort-an-array-of-objects-by-multiple-fields – dev7 Mar 17 '16 at 17:13
  • Just to check, are you sure you're using an object (`{}`) or are you rather using an array (`[]`)? When you have numeric keys, you'd generally use an array in javascript. – user162097 Mar 17 '16 at 17:15
  • return parseInt(a[0] +a[1] +a[2] +a[3], 10 ) - parseInt(b[0] +b[1] +b[2] +b[3], 10 ); – malix Mar 17 '16 at 17:15
  • So you check if the `a[0] === b[0]` and if it is, then you compare `a[3]` to `b[3]` in your sort function – Matt Burland Mar 17 '16 at 17:20
  • @user162097 to be honest I'm not an expert in Javascript, so I'm making an array of arrays, but when I get "typeof" is says "object". So I is that correct? – Pablo Mar 17 '16 at 17:34
  • @MattBurland so I'd have to make a auxiliar array? – Pablo Mar 17 '16 at 17:35
  • @malix I'm going to try, thank you – Pablo Mar 17 '16 at 17:35
  • @Pablo: I have no idea what you are trying to ask. You have an array nested inside an array. When you sort the outer array what will get passed to the `sort` function will be the two inner arrays (they'll be `a` and `b`). So you compare the first item and then you compare the last item (if necessary) – Matt Burland Mar 17 '16 at 17:37
  • @Pablo Yes, that's a quirk of javscript: it's traditonally returned "object" for `typeof []`, when we'd call it an array. However, newer versions of JS have introduced a function that allows you to distinguish between objects and arrays: `Array.isArray([]) === true && Array.isArray({}) === false` – user162097 Mar 17 '16 at 19:01

2 Answers2

6

I suggest to sort in one run with chained comparison functions.

How Array#sort() works:

If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

  • If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.

  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.

  • If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
  • compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. If inconsistent results are returned then the sort order is undefined.

In this case the compare function has two groups, one for sorting index [0] and one sorting index [3]. If the value at index [0] is equal, the the sorting for index [3] is taken. Both groups are chained with a logical or ||.

var array = [["62", 8, 0, "11"], ["62", 8, 0, "15"], ["48", 8, 0, "04"], ["48", 8, 0, "01"], ["62", 8, 0, "12"], ["48", 8, 0, "02"], ["62", 8, 0, "14"], ["48", 8, 0, "03"]];

array.sort(function (a, b) {
    return a[0].localeCompare(b[0]) || a[3].localeCompare(b[3]);
});

document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    the use of localeCompare is a bit confusing and might give unwanted results if positions 0 and 3 are actually numeric data, in spite of being strings – linuxdan Mar 17 '16 at 17:41
  • 1
    if both are numbers, you can use `return a[0] - b[0] || a[3] - b[3];` – Nina Scholz Mar 17 '16 at 17:43
  • 1
    Thanks @NinaScholz . It seems that this solved my problem. Could you do the kindness of explaining exactly what this code does? – Pablo Mar 17 '16 at 21:11
2

To me your variable looks like an Array (object indexed with integer keys) so, if it's the case, what about:

var ar = [
  ["62", 8, 0, "11"],
  ["62", 8, 0, "15"],
  ["48", 8, 0, "04"],
  ["48", 8, 0, "01"],
  ["62", 8, 0, "12"],
  ["48", 8, 0, "02"],
  ["62", 8, 0, "14"],
  ["48", 8, 0, "03"]
]

var result =  ar.map(function(a) {
  return {key: a.join(''), val: a}
}).sort(function(a, b){ 
  return parseInt(a.key, 10) - parseInt(b.key, 10);
}).map(function(a) {
  return a.val
})
console.log(result)

See this fiddle

Edit

The Object version:

var data = [{ 0:"62", 1:8, 2:0, 3:"11"},{ 0:"62", 1:8, 2:0, 3:"15"},
            { 0:"48", 1:8, 2:0, 3:"04"},{ 0:"48", 1:8, 2:0, 3:"01"},
            { 0:"62", 1:8, 2:0, 3:"12"},{ 0:"48", 1:8, 2:0, 3:"02"},
            { 0:"62", 1:8, 2:0, 3:"14"},{ 0:"48", 1:8, 2:0, 3:"03"}]

var result =  data.map(function(a) {
  return {key: [0,1,2,3].map(function(k) {return a[k]}).join(''), val: a}
}).sort(function(a, b){ 
  return parseInt(a.key, 10) - parseInt(b.key, 10);
}).map(function(a) {
  return a.val
})
console.log(result)

Updated fiddle

Edit 2

After @malixsys's comment, here's a more efficient way:

var result =  data.sort(function(a, b){ 
  return parseInt(a[0]+ a[1] + a[2] + a[3], 10) - parseInt(b[0]+ b[1] + b[2] + b[3], 10);
})

And corresponding updated fiddle

malix
  • 3,566
  • 1
  • 31
  • 41
cl3m
  • 2,791
  • 19
  • 21
  • Mapping, sorting and then mapping again seems horribly inefficient and unnecessary. You can sort it in a single step. – Matt Burland Mar 17 '16 at 17:42
  • Thank you for the extended explanation. I tried the last solution, but it didn't worked for me. – Pablo Mar 17 '16 at 21:18
  • Hey! That was my comment :) but who cares... Should have written an answer :P well done. – malix Mar 18 '16 at 14:59