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

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

本文关键字:对象 数组 属性 排序 何使用 第二个      更新时间:2023-09-26

关于使用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}]

如何根据order数组中对象的sortindex属性对items数组进行排序?这两个数组中的对象具有共同的属性id。是否有优雅的lodash/underline解决方案?

使用lodash很简单。sortBy函数会将项目移动到sortindex位置,因此我们只需要使用find来获取相应的对象,并返回其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>

如果您将订单存储为地图,那么使用香草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);
});

如果您不能假设数据已排序,请参阅此问题,例如如何根据数据创建地图。

请参阅演示:http://jsbin.com/qaquzi/1/edit?js,控制台

//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()函数从对象中获取值,的顺序传入键
  • 函数的作用是通过sortindex键对order进行排序
  • 函数的作用是:获取已排序的id数组

这是我的解决方案。如果您知道两个数组在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()