Best way to sort key based list in array of nested objects in java script

I have the following:

var list = [ {"item":[{a:5, a1:6, a2:7}, {b:3, b1:4, b2:2}]}, {"item":[{a:1, a1:2, a2:3}, {b:4, b1:5, b2:6}]}, {"item":[{a:2, a1:7, a2:4}, {b:3, b1:7, b2:1}]} ]; 

Suppose I have a list variable above, how can I sort it so that all immediate objects with the item key in list sorted in ascending order based on the key (ie "a1" or "b" ). Please note that this will not change or change the order in the list[x]["item"] list[x] , but only immediately on the list[x] elements.

The standard sort function apparently only sorts by keys inside objects inside arrays, but I want to sort based on a key located in a nested object in an array.

What is the best way to sort?

+6
source share
4 answers

So your main problem is that you need to find the object in the internal array item with the corresponding property. Since you do not know what object it will be on. Please note that the limitation here is that you will always compare the first instance found, even if more than one object in item has a comparison property. Here:

 var list = [ {"item":[{a:5, a1:6, a2:7}, {b:3, b1:4, b2:2}]}, {"item":[{a:1, a1:2, a2:3}, {b:4, b1:5, b2:6}]}, {"item":[{a:2, a1:7, a2:4}, {b:3, b1:7, b2:1}]} ]; function comparatorMaker(prop) { var findVal = function(acc, obj) { return acc || obj[prop]; }; return function(x, y) { if (!x.item && !y.item) return 0; if (x.item && !y.item) return -1; if (!x.item && y.item) return 1; var xVal = x.item.reduce(findVal, null) || 0; var yVal = y.item.reduce(findVal, null) || 0; return (xVal === yVal) ? 0 : (xVal > yVal) ? 1 : -1; }; } var myComparator = comparatorMaker('a'); list.sort(myComparator); // element 1, element 2, element 0 

What happens here is that we generate a unique comparator function for the given property name. Now it will work with anyone:

 var myComparator = comparatorMaker('b1'); list.sort(myComparator); // element 0, element 1, element 2 

The findVal function that we define when executing the comparator function is used with item.reduce . The reduction is repeated over the contents of item and returns either the value already found or searches for the value for the current item under consideration. In fact, this can be done more efficiently, as we finish the iteration of each element in item , even if we immediately find a match, but in order to demonstrate this, it will take more lines of code.

The comparator itself should return 1, 0, or -1, depending on whether the resulting resulting values ​​are more significant, equal, or less. The first few lines of the comparator function are designed to handle cases when the elements in list do not actually have the item property, because, as you formulated the question, it sounds as if it could be sometimes.

+3
source

The built-in sort Javascript method will do what you want, you just need to pass it the appropriate function (which is the difficult part). You can do this in any number of ways, but one simple way would be to create a sortBy function that takes keys, indexes, etc. that you need to get the actual value you want to sort, and returns a comparator function.

Something like that:

 function sortBy(key1, index, key2) { return function(a, b) { return a[key1][index][key2] - b[key1][index][key2]; } } 

What you then go to the sort function as follows:

 list.sort(sortBy("item", 0, "a1")); 

To sort your specific data structure by a1 .

 var list = [ {"item":[{a:5, a1:6, a2:7}, {b:3, b1:4, b2:2}]}, {"item":[{a:1, a1:2, a2:3}, {b:4, b1:5, b2:6}]}, {"item":[{a:2, a1:7, a2:4}, {b:3, b1:7, b2:1}]} ]; function sortBy(key1, index, key2) { return function(a, b) { return a[key1][index][key2] - b[key1][index][key2]; } } list.sort(sortBy("item", 0, "a1")); for (idx in list) { document.write("<pre>" + JSON.stringify(list[idx]) + "</pre>"); } 
+2
source

What is the best way to sort?

If β€œbest” means most readable, then perhaps Underscore's solution will be helpful.

How it works?

Very simple, just extends both objects of each array in one, and then compares the desired properties.

Using Underscore

 var list = [ { "item" :[{ a : 5 , a1 : 6 , a2 : 7 }, { b : 3 , b1 : 4 , b2 : 2 }]}, { "item" :[{ a : 1 , a1 : 2 , a2 : 3 }, { b : 4 , b1 : 5 , b2 : 6 }]}, { "item" :[{ a : 2 , a1 : 7 , a2 : 4 }, { b : 3 , b1 : 7 , b2 : 1 }]} ]; /// SORT FUNCTION function sortList(list, attr) { return list.sort(function(a, b) { return _.extend(a.item[0],a.item[1])[attr] > _.extend(b.item[0],b.item[1])[attr]; }) } var out = sortList(list, "a2"); for (idx in out) { document.write("<pre>" + JSON.stringify(out[idx]) + "</pre>"); } 
 <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore.js"></script> 

No dependencies

  Object.prototype.extend = function(obj) { for(i in obj) this[i] = obj[i]; return this; }; var list = [ { "item" :[{ a : 5 , a1 : 6 , a2 : 7 }, { b : 3 , b1 : 4 , b2 : 2 }]}, { "item" :[{ a : 1 , a1 : 2 , a2 : 3 }, { b : 4 , b1 : 5 , b2 : 6 }]}, { "item" :[{ a : 2 , a1 : 7 , a2 : 4 }, { b : 3 , b1 : 7 , b2 : 1 }]} ]; /// SORT FUNCTION function sortList(list, attr) { return list.sort(function(a, b) { return a.item[0].extend(a.item[1])[attr] > b.item[0].extend(b.item[1])[attr]; }) } var out = sortList(list, "b2"); for (idx in out) { document.write("<pre>" + JSON.stringify(out[idx]) + "</pre>"); } 
0
source
 var list = [ {item:[{a:5, a1:6, a2:7}, {b:3, b1:4, b2:2}]}, {item:[{a:1, a1:2, a2:3}, {b:4, b1:5, b2:6}]}, {item:[{a:2, a1:7, a2:4}, {b:3, b1:7, b2:1}]} ]; function srt(base_on){ old_idx=[]; old_srt=[]; new_srt=[]; srt_var=[]; new_list=[]; for(x=0;x<list.length;x++){ for(xx=0;xx<list[x]['item'].length;xx++){ if(list[x]['item'][xx][base_on]){ old_idx.push(x); old_srt.push(list[x]['item'][xx][base_on]); new_srt.push(list[x]['item'][xx][base_on]); } } } new_srt.sort(); for(x=0;x<new_srt.length;x++){ new_list.push(list[old_idx[old_srt.indexOf(new_srt[x])]]); } list=new_list; } 

then just call it

 srt('a1'); // to sort by a1 value 

happy try ^ _ ^

0
source

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


All Articles