Sort object by array within array?

180 views Asked by At

I have a local storage that looks like this:

Key: Savedme        
Value:
{
 "Bob":["1","1"],
 "John":["2","1"],
 "Mom":["3","1"],
 "Dad":["1","2"],
 "Tom":["3","2"],
 "Skipper42":["2","3"],
 "Hated_41":["3","3"],
 "Greeneggs":["2","2"],
 "William":["1","3"]
}

I need to somehow sort it to look like this

{
 "Bob":["1","1"],
 "Dad":["1","2"],
 "William":["1","3"]
 "John":["2","1"],
 "Greeneggs":["2","2"],
 "Skipper42":["2","3"],
 "Mom":["3","1"],
 "Tom":["3","2"],
 "Hated_41":["3","3"]
}

I've tried storing it in a matrix such as this:

var $runthrough = [[]];
$runthrough[$x,$y] = $values;

Where x is the first set of numbers, y is the next and then values is Bob, Dad etc...from there I could just do a foreach for both sections of the matrix and it would be done, HOWEVER when I use this method after it runs through one set of the objects, the second set gives an "undefined" even though I have setup some triggers to check and it's not actually going undefined.

var loadarray = JSON.parse(localStorage.getItem( 'savedme' ));
$.each(loadarray, function(k, v) {
     if(typeof k === 'undefined' || !k){
        console.error("undefined found at k!");
    };
     if(typeof v[0] === 'undefined' || !v[0]){
        console.error("undefined found at x!");
    };
     if(typeof v[1] === 'undefined' || !v[1]){
         console.error("undefined found at y!");
    };
});

so I've come to realize, I'm probably doing something wrong with arrays so I figured it would be faster to sort out the array and THEN use the same function. It HAS to be ordered like this because it's basically going to be outputted to a matrix table, I tried ordering it like this:

  {
    "1":["1","Bob"],
    "2":["1","John"],
  } 

but...the index value 1 would just be overwritten by the last value

4

There are 4 answers

0
Rick Hitchcock On BEST ANSWER

Keys cannot be sorted within an object.

However, they can be processed in order using Object.keys(object).sort().

Here, I'm outputting the object to an array – sorted by the keys' values – then displaying that array:

var obj= {
 "Bob":["1","1"],
 "John":["2","1"],
 "Mom":["3","1"],
 "Dad":["1","2"],
 "Tom":["3","2"],
 "Skipper42":["2","3"],
 "Hated_41":["3","3"],
 "Greeneggs":["2","2"],
 "William":["1","3"]
}

var arr= Object.keys(obj)
          .sort(function(a, b) {
            if(obj[a][0]===obj[b][0]) {
              return obj[a][1] - obj[b][1];
            }
            else {
              return obj[a][0] - obj[b][0];
            }
          })
          .map(function(key) {
            var o= {};
            o[key]= obj[key];
            return o;
          });

document.body.innerHTML= JSON.stringify(arr);

0
Jack Allan On

Objects properties do not have a guaranteed order in JavaScript, you need to use an Array.

Definition of an Object from ECMAScript Third Edition (pdf):

4.3.3 Object
An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.

Try a data structure like this instead:

[
 { name: "Bob", value: ["1","1"] },
 { name: "Dad", value: ["1","2"] },
 { name: "William", value: ["1","3"] },
 { name: "John", value: ["2","1"] },
 { name: "Greeneggs", value: ["2","2"] },
 { name: "Skipper42", value: ["2","3"] },
 { name: "Mom", value: ["3","1"] },
 { name: "Tom", value: ["3","2"] },
 { name: "Hated_41", value: ["3","3"] }
]

You can generate this structure like this:

var loadarray = JSON.parse(localStorage.getItem( 'savedme' ));
var sorted = [];
for (var prop in loadarray) {
    if (loadarray.hasOwnProperty(prop)) {
        sorted.push({name:prop, value:loadarray[prop]});
    }
}
sorted.sort(function(a, b) {
    var v0 = a.value[0] - b.value[0];
    return v0 == 0 ? a.value[0] - a.value[0] : v0;
});
0
Nina Scholz On

You could chain the deltas of values with the same indices.

var a = [
  { "Bob": ["1", "1"] },
  { "John": ["2", "1"] },
  { "Mom": ["3", "1"] },
  { "Dad": ["1", "2"] },
  { "Tom": ["3", "2"] },
  { "Skipper42": ["2", "3"] },
  { "Hated_41": ["3", "3"] },
  { "Greeneggs": ["2", "2"] },
  { "William": ["1", "3"] }
];

a.sort(function (a, b) {
  var aa = a[Object.keys(a)],
      bb = b[Object.keys(b)];
  if (aa[0] === bb[0]) {
    return aa[1] - bb[1];
  } else {
    return aa[0] - bb[0];
  }
});
document.querySelector("#demo").innerHTML = JSON.stringify(a, null, 4);
<div id="demo"></div>

Update 2021

const
    array = [{ Bob: ["1", "1"] }, { John: ["2", "1"] }, { Mom: ["3", "1"] }, { Dad: ["1", "2"] }, { Tom: ["3", "2"] }, { Skipper42: ["2", "3"] }, { Hated_41: ["3", "3"] }, { Greeneggs: ["2", "2"] }, { William: ["1", "3"] }];

array.sort((a, b) => {
    const
        aa = Object.values(a)[0],
        bb = Object.values(b)[0];
 
    return aa[0] - bb[0] || aa[1] - bb[1];
});

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0
Rajneesh On

Very late, but you can try this, assuming if you have an array:

var data=[{Value:
{
 "Bob":["1","1"],
 "John":["2","1"],
 "Mom":["3","1"],
 "Dad":["1","2"],
 "Tom":["3","2"],
 "Skipper42":["2","3"],
 "Hated_41":["3","3"],
 "Greeneggs":["2","2"],
 "William":["1","3"]
}}];

data.forEach((elem)=>{
    for(const property in elem.Value){
        var k = elem.Value[property];
        k.sort((a,b)=>a-b);
    }
});

console.log(data);