如何使用第二个数组中对象的相关 属性 对对象数组进行排序

how to sort an array of objects using a related property from objects in second array

有很多关于 JavaScript 排序的问题,但我没有找到任何解决这个问题的东西,所以我不认为这是重复的。

我正在从 api:

中获取这样的数据
//items array 
var items = [{id:1, name:'bill'}, {id:2, name:'sam'}, {id:3, name: mary}, {id:4, name:'jane'}]

//sort order array
var order = [{id:1, sortindex:4}, {id:2, sortindex:2}, {id:3, sortindex: 1}, {id:4, sortindex:3}]

如何根据顺序数组中对象的 sortindex 属性 对项目数组进行排序?两个数组中的对象有共同的属性id。有没有优雅的lodash/underscore解决方案?

如果您将订单存储为地图,使用香草 Javascript 是相当简单的。

var items = [{id:1, name:'bill'}, {id:2, name:'sam'}, {id:3, name: 'mary'}, {id:4, name:'jane'}];
var order = {1:4, 2:2, 3:1, 4:3};
items.sort(function (a, b) {
    return (order[a.id] > order[b.id]) - (order[a.id] < order[b.id]);
});

或者,如果您坚持使用原始数据,假设它已经按您显示的那样排序:

var items = [{id:1, name:'bill'}, {id:2, name:'sam'}, {id:3, name: 'mary'}, {id:4, name:'jane'}];
var order = [{id:1, sortindex:4}, {id:2, sortindex:2}, {id:3, sortindex: 1}, {id:4, sortindex:3}];

items.sort(function (a, b) {
    var ai = order[a.id - 1].sortindex;
    var bi = order[b.id - 1].sortindex;
    return (ai > bi) - (ai < bi);
});

如果您不能假定数据已排序,请参阅this question, for example了解如何从您的数据创建地图。

lodash 很简单。 sortBy函数会将item移动到sortindex位置,所以我们只需要用find得到对应的对象,return其sortindex属性 供 sortBy 使用。

var items = [{id:1, name:'bill'}, {id:2, name:'sam'}, {id:3, name: 'mary'}, {id:4, name:'jane'}];
var order = [{id:1, sortindex:4}, {id:2, sortindex:2}, {id:3, sortindex: 1}, {id:4, sortindex:3}];

var sorted = _.sortBy(items, function(item) {
  // sorts by the value returned here
  return _.find(order, function(ordItem) {
    // find the object where the id's match
    return item.id === ordItem.id;
  }).sortindex; // that object's sortindex property is returned
});

document.body.textContent = JSON.stringify(sorted);
<script src="https://rawgit.com/lodash/lodash/3.0.1/lodash.min.js"></script>

见演示:http://jsbin.com/qaquzi/1/edit?js,console

//items array 
var items = [{id:1, name:'bill'}, {id:2, name:'sam'}, {id:3, name: 'mary'}, {id:4, name:'jane'}]

//sort order array
var order = [{id:1, sortindex:4}, {id:2, sortindex:2}, {id:3, sortindex: 1}, {id:4, sortindex:3}]


var sortedOrder = _.sortBy(order, 'sortindex');

var bb = _.map(sortedOrder, function (i) {
    return i.id;
})

var sorted = [];

for (var i = 0, ii = bb.length; i < ii; i++) {
    for (var m = 0, mm = items.length; m < mm; m++) {
        var a = items[m];
        if (a.id == bb[i]) {
            sorted.push(items[m]);
        }
    }
}

console.log(sorted);

这是我的解决方案:

var items = [
    { id: 1, name: 'bill' },
    { id: 2, name: 'sam' },
    { id: 3, name: 'mary' },
    { id: 4, name: 'jane' }
];

var order = [
    { id: 1, sortindex: 4 },
    { id: 2, sortindex: 2 },
    { id: 3, sortindex: 1 },
    { id: 4, sortindex: 3 }
];

_(items)
    .indexBy('id')
    .at(_.pluck(_.sortBy(order, 'sortindex'), 'id'))
    .pluck('name')
    .value();
// → [ 'mary', 'sam', 'jane', 'bill' ]

这是正在发生的事情:

  • indexBy() 函数将 items 转换为对象,其中 id 值是键。
  • at() 函数从传入键的顺序 对象中获取值。
  • sortBy() 函数按 sortindex 键对 order 排序。
  • pluck() 函数获取排序后的 id 数组。

这是我的 solution。如果您知道两个数组的长度和 ID 的位置都匹配,那么这是一个简洁的解决方案:

_.chain(items)
 .merge(order)
 .sortBy('sortindex')
 .map(_.partialRight(_.omit, 'sortindex'))
 .value()

否则,如果它们不能保证被排序,那么这些项目可以用 map/find/merge 来解决。

_.chain(items)
 .map(function(item) { 
    return _.merge(item, _.find(order, {'id': item.id})); 
 })
 .sortBy('sortindex')
 .map(_.partialRight(_.omit, 'sortindex'))
 .value()