Let's say you've got three arrays of objects:
假设你有三个对象数组:
let a1 = [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'baz' }
]
let a2 = [
{ name: 'foo' },
{ name: 'bar' }
]
let a3 = [
{ name: 'bar' },
{ name: 'baz' }
]
The goal is to use a1
as a source, and add an id
field to the elements of a2
and a3
with corresponding name
fields in a1
. What is an efficient way of accomplishing this? (Note: 'efficient' here meaning 'something more elegant than loops-within-loops-within-loops'.)
目标是使用a1作为源,并在a1和a3的元素中添加id字段,并在a1中添加相应的名称字段。什么是实现这一目标的有效方法? (注意:'高效'在这里意味着'比循环内循环更优雅'。)
The result should look like this:
结果应如下所示:
a2: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' }
]
a3: [
{ id: 2, name: 'bar' },
{ id: 3, name: 'baz' }
]
5 个解决方案
#1
2
You could use a Map
for referencing the id of a given name. Then assign.
您可以使用Map来引用给定名称的ID。然后分配。
var a1 = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }, { id: 3, name: 'baz' }],
a2 = [{ name: 'foo' }, { name: 'bar' }],
a3 = [{ name: 'bar' }, { name: 'baz' }],
map = new Map(a1.map(o => [o.name, o.id]));
[a2, a3].forEach(a => a.forEach(o => o.id = map.get(o.name)));
console.log(a2);
console.log(a3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#2
2
For an alternative answer, it could be like this.
对于另一种答案,它可能是这样的。
It doesn't include loops and may be the shortest code in the answers.
它不包括循环,可能是答案中最短的代码。
const a1 = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }, { id: 3, name: 'baz' }];
const a2 = [{ name: 'foo' }, { name: 'bar' }];
const a3 = [{ name: 'bar' }, { name: 'baz' }];
let f = x => a1.filter(a => x.some(y => y.name === a.name));
console.log(f(a2));
console.log(f(a3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
1
a2.forEach((a2Elem) => a2Elem.id = a1.filter((a1Elem) => a1Elem.name === a2Elem.name)[0].id)
#4
1
I'd first take the indexes of the given names, then just map the array to be merged into:
我首先获取给定名称的索引,然后将要合并的数组映射到:
function combine(mergeInto, base) {
let indexes = base.map(e => e.name);
return mergeInto.map(e => ({
name: e.name,
id: base[indexes.indexOf(e.name)].id
}));
}
let a1 = [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'baz' }
]
let a2 = [
{ name: 'foo' },
{ name: 'bar' }
]
let a3 = [
{ name: 'bar' },
{ name: 'baz' }
]
function combine(mergeInto, base) {
let indexes = base.map(e => e.name);
return mergeInto.map(e => ({
name: e.name,
id: base[indexes.indexOf(e.name)].id
}));
}
console.log(combine(a3, a1));
#5
0
A single loop proposal - create a hash table
and then merge fields into the arrays - demo below:
单循环提议 - 创建哈希表,然后将字段合并到数组中 - 演示如下:
let a1=[{id:1,name:'foo'},{id:2,name:'bar'},{id:3,name:'baz'}], a2=[{name:'foo'},{name:'bar'}], a3=[{name:'bar'},{name:'baz'}];
// create a hash table
let hash = a1.reduce(function(p,c){
p[c.name] = c;
return p;
},Object.create(null))
// merge the results
function merge(arr) {
Object.keys(arr).map(function(e){
arr[e]['id'] = hash[arr[e].name]['id'];
});
return arr;
}
console.log(merge(a2), merge(a3));
.as-console-wrapper{top:0;max-height:100%!important;}
#1
2
You could use a Map
for referencing the id of a given name. Then assign.
您可以使用Map来引用给定名称的ID。然后分配。
var a1 = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }, { id: 3, name: 'baz' }],
a2 = [{ name: 'foo' }, { name: 'bar' }],
a3 = [{ name: 'bar' }, { name: 'baz' }],
map = new Map(a1.map(o => [o.name, o.id]));
[a2, a3].forEach(a => a.forEach(o => o.id = map.get(o.name)));
console.log(a2);
console.log(a3);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#2
2
For an alternative answer, it could be like this.
对于另一种答案,它可能是这样的。
It doesn't include loops and may be the shortest code in the answers.
它不包括循环,可能是答案中最短的代码。
const a1 = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }, { id: 3, name: 'baz' }];
const a2 = [{ name: 'foo' }, { name: 'bar' }];
const a3 = [{ name: 'bar' }, { name: 'baz' }];
let f = x => a1.filter(a => x.some(y => y.name === a.name));
console.log(f(a2));
console.log(f(a3));
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
1
a2.forEach((a2Elem) => a2Elem.id = a1.filter((a1Elem) => a1Elem.name === a2Elem.name)[0].id)
#4
1
I'd first take the indexes of the given names, then just map the array to be merged into:
我首先获取给定名称的索引,然后将要合并的数组映射到:
function combine(mergeInto, base) {
let indexes = base.map(e => e.name);
return mergeInto.map(e => ({
name: e.name,
id: base[indexes.indexOf(e.name)].id
}));
}
let a1 = [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' },
{ id: 3, name: 'baz' }
]
let a2 = [
{ name: 'foo' },
{ name: 'bar' }
]
let a3 = [
{ name: 'bar' },
{ name: 'baz' }
]
function combine(mergeInto, base) {
let indexes = base.map(e => e.name);
return mergeInto.map(e => ({
name: e.name,
id: base[indexes.indexOf(e.name)].id
}));
}
console.log(combine(a3, a1));
#5
0
A single loop proposal - create a hash table
and then merge fields into the arrays - demo below:
单循环提议 - 创建哈希表,然后将字段合并到数组中 - 演示如下:
let a1=[{id:1,name:'foo'},{id:2,name:'bar'},{id:3,name:'baz'}], a2=[{name:'foo'},{name:'bar'}], a3=[{name:'bar'},{name:'baz'}];
// create a hash table
let hash = a1.reduce(function(p,c){
p[c.name] = c;
return p;
},Object.create(null))
// merge the results
function merge(arr) {
Object.keys(arr).map(function(e){
arr[e]['id'] = hash[arr[e].name]['id'];
});
return arr;
}
console.log(merge(a2), merge(a3));
.as-console-wrapper{top:0;max-height:100%!important;}