可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
There are many questions regarding sorting with JavaScript but I didn't find anything that addresses this case so I don't believe this is a duplicate.
I'm getting data like this back from an 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}]
How can I sort the items array by the sortindex
property of the objects in the order array? The objects in the two arrays have the common property id
. Is there an elegant lodash/underscore solution?
回答1:
It's straightforward with lodash. The sortBy
function will move the items to the sortindex
position, so we just need to use find
to get the corresponding object, and return its sortindex
property for sortBy
to use.
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>
回答2:
If you store your order as a map, it's rather straight forward with vanilla 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]);
});
Or if you insist on your original data, assuming it's already sorted as you show it to be:
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);
});
If you can't assume the data is sorted, see this question, for example on how to create a map from your data.
回答3:
See in demo: 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);
回答4:
Here's my solution:
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' ]
Here's what's going on:
- The indexBy() function transforms
items
into an object, where the id
values are the keys.
- The at() function gets values from the object, in order, of the passed in keys.
- The sortBy() function sorts
order
by the sortindex
key.
- The pluck() function gets the sorted
id
array.
回答5:
Here's my solution. If you know that both arrays will match in length and location of id's, then this is a concise solution:
_.chain(items)
.merge(order)
.sortBy('sortindex')
.map(_.partialRight(_.omit, 'sortindex'))
.value()
Otherwise, if they aren't guaranteed to be sorted, then the items can be resolved with a map/find/merge.
_.chain(items)
.map(function(item) {
return _.merge(item, _.find(order, {'id': item.id}));
})
.sortBy('sortindex')
.map(_.partialRight(_.omit, 'sortindex'))
.value()