如何有条件地连接两个数组

时间:2018-04-19 07:37:44

标签: javascript arrays

我想要有条件地加入两个数组:

aData = [ { id: 1, title: `bla`}, { id: 2, title: `la`}, { id: 3, title: `lala`} ]
bData = [ { id: 1, description: `bla`} ]

在第一种情况下,我希望只能获得具有合并属性的匹配结果(aData+bData

matchingIdsResult = [ { id: 1, title: `bla`, description: `bla` } ]

在第二种情况下,我希望获得不匹配的结果 - 只有来自aData的对象,bData中没有{ID>}

unmathingIdsResult = [ { id: 2, title: `la`}, { id: 3, title: `lala`} ]

我正在玩.map.reduce并实现目前为止:

const data: any = aData.concat(bData).reduce((acc, x) => {
    acc[x.id] = Object.assign(acc[x.id] || {}, x);
    return acc;
}, {});

但是在这种情况下,到目前为止,我确实将所有aData个对象与匹配的bData属性合并,这实际上并不是我想要的。

3 个答案:

答案 0 :(得分:1)

idbData创建Map。使用reduce迭代aData。如果对象idbDataMap中,则将组合对象推入第一个子数组。如果没有,到第二个。获取matchingIdsResultunmatchingIdsResult destructuring的结果:reduce:



const aData = [{"id":1,"title":"bla"},{"id":2,"title":"la"},{"id":3,"title":"lala"}];
const bData = [{"id":1,"description":"bla"}];

const bDataMap = new Map(bData.map((o) => [o.id, o]));

const [matchingIdsResult, unmatchingIdsResult] = aData.reduce((r, o) => {
  if(bDataMap.has(o.id)) r[0].push(Object.assign({}, o, bDataMap.get(o.id)));
  else r[1].push(o);
  
  return r;
}, [[], []]);
  
console.log(matchingIdsResult);
console.log(unmatchingIdsResult);




如果您想跳过bDataMap的创建,可以使用Array.find()。使用Map(n - aData.length,m - bData.length),复杂度将变为O(n * m)而不是o(n + m),但对于小数组,这可能是微不足道的:



const aData = [{"id":1,"title":"bla"},{"id":2,"title":"la"},{"id":3,"title":"lala"}];
const bData = [{"id":1,"description":"bla"}];

const [matchingIdsResult, unmatchingIdsResult] = aData.reduce((r, o) => {
  const match = bData.find(({ id }) => id === o.id);

  if(match) r[0].push(Object.assign({}, o, match));
  else r[1].push(o);
  
  return r;
}, [[], []]);
  
console.log(matchingIdsResult);
console.log(unmatchingIdsResult);




答案 1 :(得分:1)

您可以将第一个数组作为不匹配的起始值,并检查第二个数组并拆分匹配的对象或推送到不匹配的数组。

var aData = [{ id: 1, title: 'bla' }, { id: 2, title: 'la' }, { id: 3, title: 'lala' }],
    bData = [{ id: 1, description: 'bla' }],
    unmatching = aData,
    matching = [];

bData.forEach(o => {
    var index = unmatching.findIndex(({ id }) => o.id = id);
    if (index === -1) {
        unmatching.push(o);
    } else {
        matching.push(Object.assign({}, unmatching.splice(index, 1)[0], o));
    }
});

console.log(matching);
console.log(unmatching);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:1)

如果id存在与否,则创建一个不匹配和匹配检查的地图。

当你有两个单独的matchedunmatched的awway时,只需将matched数组(基于ID)与另一个包含的数组合并数据。

aData = [ { id: 1, title: `bla`}, { id: 2, title: `la`}, { id: 3, title: `lala`} ]
bData = [ { id: 1, description: `bla`} ];
var unmatched = [],
   matched = [];
aData.every(x=> bData.map(e=> e.id).includes(x.id) ? matched.push(x) : unmatched.push(x))
matched = matched.map(x=> Object.assign(x, bData.find(e=> e.id ===x.id )))
console.log("Matched " , matched)

console.log("Un matched", unmatched)
.as-console-wrapper { max-height: 100% !important; top: 0; }