在我的职业生涯中,我多次遇到这个问题。我已经用谷歌搜索,但没有在那些结果或StackOverflow上找到精确匹配。
考虑到我有以下对象数组:
let objects = [
{id: 'doe', descr: 'a deer'},
{id: 'baz', descr: 'non-sense'},
{id: 'ray', descr: 'a drop'},
{id: 'foo', descr: 'effed'},
{id: 'bar', descr: 'beyond'}
];
我只想获取id
与以下数组之一匹配的数组元素, 将它们返回与 order匹配的数组:
let objectsOrder = ['foo', 'bar', 'baz'];
我实际上已经设计了几种解决方案,并且将在下面使用reduce
提出一个解决方案(我在其他尝试中也使用过forEach
,但不会提出解决方案)。我猜也可以先过滤,然后再(自定义)排序,但这似乎要重复两次。也许另一种选择是使用lodash
中的一种或多种方法,尽管我不确定那会是什么。
答案 0 :(得分:2)
您可以使用Map
并按所需顺序映射对象。
var objects = [
{ id: 'doe', descr: 'a deer' },
{ id: 'baz', descr: 'non-sense' },
{ id: 'ray', descr: 'a drop' },
{ id: 'foo', descr: 'effed' },
{ id: 'bar', descr: 'beyond' }
],
objectsOrder = ['foo', 'bar', 'baz'],
result = objectsOrder.map(Map.prototype.get, new Map(objects.map(o => [o.id, o])));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
如果某些id
未知,则可以为真实项目添加过滤器。
var objects = [
{ id: 'doe', descr: 'a deer' },
{ id: 'baz', descr: 'non-sense' },
{ id: 'ray', descr: 'a drop' },
{ id: 'foo', descr: 'effed' },
{ id: 'bar', descr: 'beyond' }
],
objectsOrder = ['foo', 'bar', 'unknown'],
result = objectsOrder
.map(Map.prototype.get, new Map(objects.map(o => [o.id, o])))
.filter(Boolean);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:0)
以下代码位于:https://repl.it/@dexygen/orderFilteredObjects
let objects = [
{id: 'doe', descr: 'a deer'},
{id: 'baz', descr: 'non-sense'},
{id: 'ray', descr: 'a drop'},
{id: 'foo', descr: 'effed'},
{id: 'bar', descr: 'beyond'}
];
let objectsOrder = ['foo', 'bar', 'baz'];
let prunedObjects = objects.reduce((pruned, obj) => {
let orderIndex = objectsOrder.indexOf(obj.id);
if (orderIndex >= 0) {
pruned[orderIndex] = obj;
}
return pruned;
}, []);
console.log(JSON.stringify(prunedObjects)); //[{"id":"foo","descr":"effed"},{"id":"bar","descr":"beyond"},{"id":"baz","descr":"non-sense"}]
答案 2 :(得分:0)
这可以轻松地通过forEach()
循环来完成。无需使用reduce()
。
let objects = [
{id: 'doe', descr: 'a deer'},
{id: 'baz', descr: 'non-sense'},
{id: 'ray', descr: 'a drop'},
{id: 'foo', descr: 'effed'},
{id: 'bar', descr: 'beyond'}
];
let objectsOrder = ['foo', 'bar', 'baz'];
let res = [];
objects.forEach((obj)=>{
var id = obj.id;
var idIndex = objectsOrder.indexOf(id);
if(idIndex !== -1){
res[idIndex] = obj;
}
});
console.log(res);
答案 3 :(得分:0)
另一种方法是通过lodash _.keyBy以适合对象键访问的形式获取输入数据:
let objects = [{id: 'doe', descr: 'a deer'},{id: 'baz', descr: 'non-sense'},{id: 'ray', descr: 'a drop'},{id: 'foo', descr: 'effed'},{id: 'bar', descr: 'beyond'}];
let objectsOrder = ['foo', 'bar', 'baz'];
var keyedObjects = _.keyBy(objects, 'id')
var result = objectsOrder.map(x => keyedObjects[x])
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
通过这种方式,您可以在objectsOrder
上进行映射以保留订单,只需使用键即可在map函数中获得访问权限。
答案 4 :(得分:-1)
您不需要如此复杂的逻辑。只需映射每个objectsOrder
值并在objects
数组上获取相应的值
let objects = [
{id: 'doe', descr: 'a deer'},
{id: 'baz', descr: 'non-sense'},
{id: 'ray', descr: 'a drop'},
{id: 'foo', descr: 'effed'},
{id: 'bar', descr: 'beyond'}
];
let objectsOrder = ['foo', 'bar', 'baz'];
console.log(
objectsOrder.map(a=>objects.find(b=>b.id==a))
)