Javascript 根据id从另一个数组中分配一些字段,并根据值类型获得最终输出?
我想根据id值将字段“type”和“publisher”分配给arr1,同时我想根据类型分配数组 所需的输出是Javascript 根据id从另一个数组中分配一些字段,并根据值类型获得最终输出?,javascript,arrays,node.js,performance,functional-programming,Javascript,Arrays,Node.js,Performance,Functional Programming,我想根据id值将字段“type”和“publisher”分配给arr1,同时我想根据类型分配数组 所需的输出是 arr1 = [ { id : 1, name : 'book1', description: 'some text' }, { id : 2, name : 'book2', description: 'some text'
arr1 = [
{ id : 1,
name : 'book1',
description: 'some text'
},
{ id : 2,
name : 'book2',
description: 'some text'
},
{ id : 3,
name : 'book3',
description: 'some text'
}
]
arr2 = [
{ id : 1,
name : 'book1',
type : 'thriller',
publisher : 'some x',
isbn : '2983457928435',
date : '20-1-2014'
},
{ id : 2,
name : 'book2',
type : 'action',
publisher : 'some x',
isbn : '2983457928435',
date : '20-1-2014'
},
{ id : 3,
name : 'book3',
type : 'thriller',
publisher : 'some y',
isbn : '2983457928435',
date : '20-1-2014'
}
]
性能是关键问题。我可以实现以上一个使用2个功能,但我想实现它在单一的功能
Edit1:-在arr1中,我从数据库(mongodb)中获得了一些其他字段以及上述字段。为了简单起见,我已经包括了任何必要的东西
目前,我通过以下两个功能来实现这一点
职能1:-
arr3 = {
'thriller': [
{ id: 1, name: 'book1', type: 'thriller', publisher: 'some x', description: 'some text' },
{ id: 3, name: 'book3', type: 'thriller', publisher: 'some y', description: 'some text' }
],
'action': [
{ id: 2, name: 'book2', type: 'action', publisher: 'some x', description: 'some text' }]
}
职能2:-
let result = arr1.map((e) => {
for(let element of arr2){
if(e.id === element.id)
{
e['type'] = element.type
e['publisher'] = element.publisher
}
}
return e
})
我想要的是将这两种功能结合起来,并在单个函数调用中执行。
arr1=[
{id:1,
名称:'book1',
描述:'此处有一些文字'
},
{id:2,
名称:'book2',
描述:'此处有一些文字'
},
{id:3,
名称:'book3',
描述:'此处有一些文字'
}
]
arr2=[
{id:1,
名称:'book1',
类型:“thriller”,
出版商:“一些x”
},
{id:2,
名称:'book2',
键入:“操作”,
出版商:“一些x”
},
{id:3,
名称:'book3',
类型:“thriller”,
出版者:“一些y”
}
]
让结果=arr1.减少(功能(acc,e){
for(arr2的let元素){
if(e.id==element.id)
{
e['type']=element.type
e['publisher']=element.publisher
打破
}
}
var key=e['type'];
如果(!acc[键]){
acc[键]=[];
}
acc[键]。按下(e);
返回acc;
}, {});
console.log(result)
一旦执行此操作,我可以想象您将遇到的唯一值得注意的性能问题就会出现:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
}
let output = groupBy(result, 'type');
这种嵌套循环大大增加了迭代次数。对于arr1
的每个元素,我们(可能)循环了arr2
的每个元素,给出了arr1.length
(最佳情况)和arr1.length*arr2.length
(最坏情况)之间的迭代次数。如果您使用的是真正的大数据集,那么这种差异可能很明显
通常,解决方案是将数组索引到对象或贴图中,这样可以更快地查找。转换阵列需要一些时间,但是循环运行得更快
以下是我的建议:
arr1
转换为以下形式的索引bookscriptions
:
{id:{name,id,description}}
arr2
转换为以下格式的索引bookMetadata
:
{id:{name,id,type,publisher}
书籍
dat将这些按id合并到:[{name,id,type,description,publisher}]
groupBy
进行最终分组//按唯一属性对值数组进行索引
常数indexBy=(k,xs)=>xs.reduce(
(acc,x)=>Object.assign(acc,{[x[k]]:x}),
{}
);
//按特定属性对对象数组进行分组
常量groupBy=(k,xs)=>xs.reduce(
(acc,x)=>Object.assign(acc,{
[x[k]]:附件[x[k]]
?附件[x[k].混凝土(x)
:[x]
}),
{}
);
//返回不带重复项的数组
const uniques=xs=>Array.from(新集合(xs));
//使用Object.assign按索引键合并两个索引
常量合并索引=(i1,i2)=>
独特的([
…对象键(i1),
…对象.键(i2)
]).map(k=>Object.assign({},i1[k],i2[k]);
const bookscriptions=indexBy(“id”,getDescriptions());
const bookmatadata=indexBy(“id”,getMetadata());
const books=合并索引(图书描述、图书元数据);
const booksByType=groupBy(“type”,books);
console.log(booksByType);
函数getDescriptions(){return[{id:1,name:“book1”,description:“some text”},{id:2,name:“book2”,description:“some text”},{id:3,name:“book3”,description:“some text”};};
函数getMetadata(){return[{id:1,name:“book1”,type:“thriller”,publisher:“some x”},{id:2,name:“book2”,type:“action”,publisher:“some x”},{id:3,name:“book3”,type:“thriller”,publisher:“some y”}
你能提供你正在使用的两个函数吗?但我想用一个函数来实现它。
为什么?调用函数不会影响性能。那你为什么需要arr1
呢?@离开我的草坪,@Jonas W,看看Edit1I我同意你的观点“arr1.length(最佳情况)和arr1.length*arr2.length(最坏情况)”。但在我的真实案例中,在arr2以及类型和发布者字段中,我有一些其他文件,我不希望它们出现在最终输出中,这是我只能分配类型和发布者字段的方式。你能给我建议一些其他更好的方法来省略for循环,然后if条件吗?因为我只需要type和publisher字段,但arr2包含一些其他额外字段。此函数是当前的合并逻辑:k=>Object.assign({},i1[k],i2[k])
。您可以手动创建一个新对象。例如:k=>({id:i1[k].id,type:i2[k].type})
在上述功能中,它必须循环数组以分配和追加字段。这个假设正确吗?我已经测试了你的代码在数组中的长度为18项,并比较了计算时间,这需要一些额外的时间。我编写的代码在18项中不会更快。。。当你说你担心性能时,我以为你说的更像是1000件物品;)尝试100、1000和10000,看看是否有不同……我看你已经接受了自己的答案,其中没有包括与原始问题不同的方法。我添加了一个性能测试来向您展示,对于更大的数据集,您将开始看到差异。如果您仍然认为嵌套循环是您的b,请告诉我
arr1.reduce(function (acc, e) {
for (let element of arr2) {
/* ... */
}
})