Javascript 在另一个数组';s指令

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:

在我的职业生涯中,我不止一次遇到过这个问题。我在谷歌上搜索过,在这些结果或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
与以下数组中的一个元素匹配的数组元素,并在与以下顺序匹配的数组中返回它们:

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(结果)


Try
objectsOrder.map(a=>objects.find(b=>b.id==a))
没有尝试…?@GeorgeJempty该尝试实际上应该是寻求改进的问题的一部分。@GeorgeJempty这是一个有着强有力答案的有力问题。不相关。在我看来,最简单、最简单的方法就是简单地将对象转换为通过id设置
键的
。然后简单地通过键从对象获取值。发布了一个解决方案。这不应该是一个
O(n2)
complexity
find
inside
map
@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))
是所需要的一切。@vlaz
filter
本身是不够的,结果需要以特定的顺序出来。首先使用
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 of
objectsOrder
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"}]