我有两个数组:
数组1:
[
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
]
和数组2:
[
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
]
我需要根据id
合并这两个数组,并得到:
[
{ id: "abdc4051", date: "2017-01-24", name: "ab" },
{ id: "abdc4052", date: "2017-01-22", name: "abc" }
]
如何在不通过Object.keys
迭代的情况下执行此操作?
答案 0 :(得分:15)
即使您要合并的数组大小不同,此解决方案也适用。而且,即使发生匹配的键也具有不同的名称。
const arr1 = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" },
{ id: "abdc4053", date: "2017-01-22" }
];
const arr2 = [
{ nameId: "abdc4051", name: "ab" },
{ nameId: "abdc4052", name: "abc" }
];
现在要合并这些地图,请按以下方式使用地图:
const map = new Map();
arr1.forEach(item => map.set(item.id, item));
arr2.forEach(item => map.set(item.nameId, {...map.get(item.nameId), ...item}));
const mergedArr = Array.from(map.values());
这应该导致:
[
{
"id": "abdc4051",
"date": "2017-01-24",
"nameId": "abdc4051",
"name": "ab"
},
{
"id": "abdc4052",
"date": "2017-01-22",
"nameId": "abdc4052",
"name": "abc"
},
{
"id": "abdc4053",
"date": "2017-01-22"
}
]
答案 1 :(得分:13)
您可以一行完成
let arr1 = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
];
let arr2 = [
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
];
const mergeById = (a1, a2) =>
a1.map(itm => ({
...a2.find((item) => (item.id === itm.id) && item),
...itm
}));
console.log(mergeById(arr1, arr2));
最终数组将只包含两个数组都匹配的ID
答案 2 :(得分:9)
你可以这样做 -
arr1
如果arr2
和let arr1 = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
];
let arr2 = [
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
];
let merged = [];
for(let i=0; i<arr1.length; i++) {
merged.push({
...arr1[i],
...(arr2.find((itmInner) => itmInner.id === arr1[i].id))}
);
}
console.log(merged);
的顺序不同,请使用以下代码:
arr1
如果arr2
和let arr1 = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
];
let arr2 = [
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
];
let merged = [];
for(let i=0; i<arr1.length; i++) {
merged.push({
...arr1[i],
...arr2[i]
});
}
console.log(merged);
的订单相同,请使用此
{{1}}
答案 3 :(得分:8)
您可以使用任意数量的数组并映射到相同的索引新对象。
var array1 = [{ id: "abdc4051", date: "2017-01-24" }, { id: "abdc4052", date: "2017-01-22" }],
array2 = [{ id: "abdc4051", name: "ab" }, { id: "abdc4052", name: "abc" }],
result = [array1, array2].reduce((a, b) => a.map((c, i) => Object.assign({}, c, b[i])));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 4 :(得分:2)
您可以使用数组方法
let arrayA=[
{id: "abdc4051", date: "2017-01-24"},
{id: "abdc4052", date: "2017-01-22"}]
let arrayB=[
{id: "abdc4051", name: "ab"},
{id: "abdc4052", name: "abc"}]
let arrayC = [];
function isBiggerThan10(element, index, array) {
return element > 10;
}
arrayA.forEach(function(element){
arrayC.push({
id:element.id,
date:element.date,
name:(arrayB.find(e=>e.id===element.id)).name
});
});
console.log(arrayC);
//0:{id: "abdc4051", date: "2017-01-24", name: "ab"}
//1:{id: "abdc4052", date: "2017-01-22", name: "abc"}
&#13;
答案 5 :(得分:2)
我们可以在这里使用lodash。 _.merge可以按预期工作。它可以与存在的通用密钥一起使用。
_.merge(array1, array2)
答案 6 :(得分:2)
这是使用reduce和Object.assign的O(n)解决方案
const joinById = ( ...lists ) =>
Object.values(
lists.reduce(
( idx, list ) => {
list.forEach( ( recod ) => {
if( idx[ recod.id ] )
idx[ recod.id ] = Object.assign( idx[ recod.id ], recod )
else
idx[ recod.id ] = recod
} )
return idx
},
{}
)
)
每个列表都简化为单个对象,其中键是id,值是对象。如果给定键上已经有一个值,它将被调用object.assign和当前记录。
这是通用的O(n * m)解决方案,其中n是记录数,m是键数。这仅适用于有效的对象键。您可以将任何值转换为base64,并在需要时使用它。
const join = ( keys, ...lists ) =>
lists.reduce(
( res, list ) => {
list.forEach( ( record ) => {
let hasNode = keys.reduce(
( idx, key ) => idx && idx[ record[ key ] ],
res[ 0 ].tree
)
if( hasNode ) {
const i = hasNode.i
Object.assign( res[ i ].value, record )
res[ i ].found++
} else {
let node = keys.reduce( ( idx, key ) => {
if( idx[ record[ key ] ] )
return idx[ record[ key ] ]
else
idx[ record[ key ] ] = {}
return idx[ record[ key ] ]
}, res[ 0 ].tree )
node.i = res[ 0 ].i++
res[ node.i ] = {
found: 1,
value: record
}
}
} )
return res
},
[ { i: 1, tree: {} } ]
)
.slice( 1 )
.filter( node => node.found === lists.length )
.map( n => n.value )
这与joinById方法基本相同,不同之处在于它保留一个索引对象来标识要加入的记录。记录存储在数组中,索引存储给定键集的记录位置以及在其中找到的列表数。
每次遇到相同的键集时,都会在树中找到该节点,并更新其索引处的元素,并且增加被发现的次数。
最后,将idx对象与切片一起从数组中删除,在每个集合中未找到的所有元素都将删除。这使它成为内部联接,您可以删除此过滤器并具有完整的外部联接。
最后,每个元素都映射到其值,并且您有了合并的数组。
答案 7 :(得分:1)
我遍历第一个数组并在第二个数组上使用 function updateInputs(data) {
var from = data.from;
var to = data.to;
var rangeFrom, rangeTo;
switch (data.input.getAttribute("data-range")) {
case "rangeSalary":
rangeFrom = $("rangeFromSalary");
rangeTo = $("rangeToSalary");
break;
case "rangeAge":
rangeFrom = $("rangeFromAge");
rangeTo = $("rangeToAge");
break;
// ...
}
if (rangeFrom && rangeTo) {
rangeFrom.prop("value", from);
rangeTo.prop("value", to);
}
table.draw();
}
方法来查找 .find
相等的匹配项并返回结果。
id
答案 8 :(得分:1)
这里是单行(数组中元素的顺序并不重要,假设存在 1 对 1 的关系):
var newArray = array1.map(x=>Object.assign(x, array2.find(y=>y.id==x.id)))
答案 9 :(得分:1)
您可以按如下方式递归合并它们:
function mergeRecursive(obj1, obj2) {
for (var p in obj2) {
try {
// Property in destination object set; update its value.
if (obj2[p].constructor == Object) {
obj1[p] = this.mergeRecursive(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
} catch (e) {
obj1[p] = obj2[p];
}
}
return obj1;
}
arr1 = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
];
arr2 = [
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
];
mergeRecursive(arr1, arr2)
console.log(JSON.stringify(arr1))
&#13;
答案 10 :(得分:1)
无论您合并的顺序如何,
function merge(array,key){
let map = {};
array.forEach(val=>{
if(map[val[key]]){
map[val[key]] = {...map[val[key]],...val};
}else{
map[val[key]] = val;
}
})
return Object.keys(map).map(val=>map[val]);
}
let b = [
{ id: "abdc4051", name: "ab" },
{ id: "abdc4052", name: "abc" }
];
let a = [
{ id: "abdc4051", date: "2017-01-24" },
{ id: "abdc4052", date: "2017-01-22" }
];
console.log(merge( [...a,...b], 'id'));
答案 11 :(得分:0)
要合并id
上的两个数组,假设它们的长度相等:
arr1.map(item => ({
...item,
...arr2.find(({ id }) => id === item.id),
}));
答案 12 :(得分:0)
如果您有2个数组需要基于值进行合并,即使它们的排列顺序不同
let arr1 = [
{ id:"1", value:"this", other: "that" },
{ id:"2", value:"this", other: "that" }
];
let arr2 = [
{ id:"2", key:"val2"},
{ id:"1", key:"val1"}
];
您可以这样做
const result = arr1.map(item => {
const obj = arr2.find(o => o.id === item.id);
return { ...item, ...obj };
});
console.log(result);
答案 13 :(得分:0)
这些解决方案均不适用于我的情况:
注释:
import { keyBy, values } from 'lodash';
interface IStringTMap<T> {
[key: string]: T;
}
type IIdentified = {
id?: string | number;
};
export function mergeArrayById<T extends IIdentified>(
array1: T[],
array2: T[]
): T[] {
const mergedObjectMap: IStringTMap<T> = keyBy(array1, 'id');
const finalArray: T[] = [];
for (const object of array2) {
if (object.id && mergedObjectMap[object.id]) {
mergedObjectMap[object.id] = {
...mergedObjectMap[object.id],
...object,
};
} else {
finalArray.push(object);
}
}
values(mergedObjectMap).forEach(object => {
finalArray.push(object);
});
return finalArray;
}
答案 14 :(得分:0)
我能够通过两个数组的嵌套映射并更新初始数组来实现这一点:
member.map(mem => {
return memberInfo.map(info => {
if (info.id === mem.userId) {
mem.date = info.date;
return mem;
}
}
}
答案 15 :(得分:0)
嗯......假设两个数组的长度相同,我可能会这样做:
var newArr = []
for (var i = 0; i < array1.length; i++ {
if (array1[i].id === array2[i].id) {
newArr.push({id: array1[i].id, date: array1[i].date, name: array2[i].name});
}
}
答案 16 :(得分:-1)
使用开源项目jinqJs非常简单 -
//Use jsJinq.com open source library
var list1= [{Location: 'NY', People: 200}, {Location: 'TX', People: 500}];
var list2= [{Location: 'NY', State: 'New York'}, {Location: 'TX', State: 'Texas'}]
var result = new jinqJs().from(list1).join(list2).on('Location').select();
document.body.innerHTML += '<pre>' + JSON.stringify(result, null, 4) + '</pre>';
<script src="https://rawgit.com/fordth/jinqJs/master/jinqjs.js"></script>