Javascript 在另一个数组';s指令
在我的职业生涯中,我不止一次遇到过这个问题。我在谷歌上搜索过,在这些结果或StackOverflow上都没有找到精确的匹配 假设我有以下对象数组:Javascript 在另一个数组';s指令,javascript,arrays,lodash,Javascript,Arrays,Lodash,在我的职业生涯中,我不止一次遇到过这个问题。我在谷歌上搜索过,在这些结果或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:
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
与以下数组中的一个元素匹配的数组元素,并在与以下顺序匹配的数组中返回它们:
let objectsOrder = ['foo', 'bar', 'baz'];
实际上,我已经设计了两个解决方案,并将在下面使用reduce
作为答案演示一个解决方案(我在其他尝试中也使用了forEach
,但不会演示)。我想它也可以通过先过滤,然后(自定义)排序来完成,但这似乎会重复两次。也许另一种选择是使用lodash中的一种(或多种)方法,尽管我不确定该方法是什么。以下代码位于:
这可以通过
forEach()
循环轻松完成。无需使用reduce()
let对象=[
{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'];
设res=[];
objects.forEach((obj)=>{
变量id=对象id;
var ididex=objectsOrder.indexOf(id);
如果(idIndex!=-1){
res[idIndex]=obj;
}
});
控制台日志(res)代码>您不需要如此复杂的逻辑。只需映射每个objectsOrder
值,并在对象
数组中获取相应的值
let对象=[
{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'];
console.log(
objectsOrder.map(a=>objects.find(b=>b.id==a))
)
您可以拍摄一张地图,并按所需顺序获取对象的地图
var对象=[
{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,newmap(objects.map(o=>[o.id,o]));
控制台日志(结果)代码>
.as console wrapper{max height:100%!important;top:0;}
另一种方法是通过lodash以适合对象键访问的形式获取输入数据:
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'}];
让objectsOrder=['foo','bar','baz'];
var keyedObjects=ux.keyBy(对象“id”)
var result=objectsOrder.map(x=>keyedObjects[x])
console.log(结果)
TryobjectsOrder.map(a=>objects.find(b=>b.id==a))
没有尝试…?@GeorgeJempty该尝试实际上应该是寻求改进的问题的一部分。@GeorgeJempty这是一个有着强有力答案的有力问题。不相关。在我看来,最简单、最简单的方法就是简单地将对象转换为通过id设置键的
。然后简单地通过键从对象获取值。发布了一个解决方案。这不应该是一个O(n2)
complexityfind
insidemap
@AnkitAgarwal我在回答中没有提到复杂性,如果看起来是这样,请道歉。事实上,我的答案是O(n*n)
,但OP没有说明他在寻找一个最快的算法,只是为他的问题寻找一个解决方案。@AnkitAgarwal它是O(n^m),因为这两个数组的长度不同。@LuisfelipeDejesusMunoz我没有一个本身无法解决的问题,因为我发布了自己的解决方案作为答案。在这种情况下,我不想要一个O(n*n)的替代算法,因为我的reduce算法比这个算法快。而且.forEach
可能更合适。filter
@vlaz不会跟随你。请再次光临当array.filter
存在时,无需循环并建立一个新的筛选对象数组。filter
正是为了这个目的而存在的<代码>对象.filter(obj=>objectsOrder.includes(obj.id))
是所需要的一切。@vlazfilter
本身是不够的,结果需要以特定的顺序出来。首先使用filter
需要再次迭代OK,我错过了。请您将其格式设置得更好(因此行不会太长)谢谢--我会自己做,但必须很快离开。哪一行太长?可能先点击刷新?如何使用Map.prototype.get
知道如何查看此参数?Map.prototype.get
是函数/cb,Map将函数与thisArg
一起使用,Map
的实例。如果对象不在objects
中,result
将在其位置上有一个不需要的空值。这将继续重新扫描objectsOrder
数组,为对象中的每个条目找到匹配项。首先从objectsOrder
构建一个查找散列要简单得多-在一个操作中将它简化为{foo:0,bar:1,baz:2}
,然后执行orderIndex=order[obj.id]
来简单地获取值。@vlaz我还以为数组已经为indexOf优化了吗?但是你是对的,如果我没有从其他来源获得订单,最好将其设置为对象,而不是数组。它仍然会触发对数组的O(n)扫描。因为涉及到两个数组,所以复杂性为O(n^m),其中n
length ofobjectsOrder
和m
是对象的长度。预计算散列将是O(n),之后的每次提取将是O(1)。
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"}]