最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - best way to sort list based on key in nested object array in java script - Stack Overflow

programmeradmin3浏览0评论

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}]}
];

Assume that I have the variable list above, how can I sort it such that all the immediate objects with the item key in the list are sorted in ascending order based on a key (i.e. "a1" or "b"). Note that it would not change or reorder the list in list[x]["item"], but only the immediate items in list[x].

The standard sort function appears to sort only on keys within objects within 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 this?

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}]}
];

Assume that I have the variable list above, how can I sort it such that all the immediate objects with the item key in the list are sorted in ascending order based on a key (i.e. "a1" or "b"). Note that it would not change or reorder the list in list[x]["item"], but only the immediate items in list[x].

The standard sort function appears to sort only on keys within objects within 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 this?

Share Improve this question edited Oct 27, 2014 at 21:33 Weafs.py 23k9 gold badges57 silver badges79 bronze badges asked Oct 16, 2014 at 23:40 RolandoRolando 62.8k104 gold badges281 silver badges422 bronze badges 4
  • 6 The standard sort will do, but you'd have to build a parator function that does what you need. – elclanrs Commented Oct 16, 2014 at 23:43
  • What @elclanrs said... you'll need a parator function that you can pass into Array.sort in a format of function (a, b) { /* return < 0 if a is less than b; */ }, where a, and b, are array elements. – lxe Commented Oct 16, 2014 at 23:53
  • Can you provide the expected output – harishr Commented Oct 28, 2014 at 5:32
  • @Rolando, it says "the current answers do not contain enough detail," but without some feedback it's hard to know what you feel is unaddressed. Three of the four answers seem like plete and explained solutions to me, but maybe we've misunderstood your question? – Semicolon Commented Oct 28, 2014 at 8:13
Add a ment  | 

4 Answers 4

Reset to default 4 +50

So your main issue is that you need to find an object in the internal item array with the matching property. Since you don't know what object it will be located on. Note that a limitation here is that you're always going to be paring on the first found instance, even if more than one object in item possesses the parison property. Here goes:

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 paratorMaker(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 = paratorMaker('a');

list.sort(myComparator); // element 1, element 2, element 0

What's happening here is that we generate a unique parator function for a given property name. It will now work with any:

var myComparator = paratorMaker('b1');

list.sort(myComparator); // element 0, element 1, element 2

The findVal function that we define when making the parator function is used with item.reduce. The reduction iterates over the contents of item and returns either the already-found value or looks for the value on the current element under examination. This could be done more efficiently, actually, since we end up iterating every element in item even if we find a match immediately, but it would take more lines of code to demonstrate that so I kept it simple.

The parator itself should return 1, 0 or -1 depending on whether the resulting values are found to be greater-lesser, equal, or lesser-greater. The first few lines of the parator function are just to handle cases where elements in list do not actually have the item property, since the way you phrased the question, it sounded like this might sometimes be the case.

Javascript's built-in sort method will do what you want, you just have to pass it the appropriate function (which is the tricky part). You can do it any number of ways really, but one easy way would be by creating a sortBy function that takes the keys, indexes, etc. that you need to get the actual value you want to sort on and returns a parator function.

Something like this:

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

Which you'd then pass to the sort function like this:

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

Which would sort your particular 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>");
}

What is the best way to sort this?

If "best" means the most readable, perhaps the Underscore solution will be useful.

How to it works?

Very simple, just extends both object of each array in one and then pare 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./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>");
    }

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 this

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

happy try ^_^

发布评论

评论列表(0)

  1. 暂无评论