如何根据两个对象键合并两个不同长度的对象数组

How to merge two object arrays of differing length, based on two object key

我有 2 个数组,如果它们具有相同的两个对象键,我想合并它们。

如果找不到匹配项,仍然保留该对象,但值为0。

输入示例

withdrawal: [
    {
        "id": "a1",
        "withdrawalAmount": 300,
        "user": "John"
    },
    {
        "id": "b2",
        "withdrawalAmount": 100,
        "user": "Mike"
    }
    {
        "id": "c3",
        "withdrawalAmount": 33,
        "user": "John"
    }
]


deposit: [
    {
        "id": "a1",
        "depositAmount": 123,
        "user": "John"
    },
    {
        "id": "c3",
        "depositAmount": 44,
        "user": "John"
    },
]

预期输出

transactions: [
    {
        "id": "a1",
        "depositAmount": 123,
        "withdrawalAmount": 300,
        "user": "John"
    },
    {
        "id": "b2",
        "depositAmount": 0,
        "withdrawalAmount": 100,
        "user": "Mike"
    },
    {
        "id": "c3",
        "depositAmount": 44,
        "withdrawalAmount": 33
        "user": "John"
    },
]

这是我到目前为止尝试过的函数,但由于两个输入数组的长度不同,所以它不起作用。

function mergeArrayObjects(arr1, arr2) {
    return arr1.map((item, i) => {
      if (item.user === arr2[i].user) {
        //merging two objects
        return Object.assign({}, item, arr2[i])
      }
    })
  }

您可以通过使用 Array.reduceid 值作为键和 deposit 和 [=17= 的对象处理取款和存款列表来实现您想要的结果] 金额作为价值;然后您可以使用该对象的值来创建 transactions 数组:

const withdrawal = [{
    "id": "a1",
    "withdrawalAmount": 300,
    "user": "John"
  },
  {
    "id": "b2",
    "withdrawalAmount": 100,
    "user": "Mike"
  }
]

const deposit = [{
    "id": "a1",
    "depositAmount": 123,
    "user": "John"
  },
  {
    "id": "c3",
    "depositAmount": 44,
    "user": "John"
  }
]

const transactions = Object.values(
  withdrawal
    .concat(deposit)
    .reduce((c, { id, depositAmount, withdrawalAmount, ...rest }) => {
      c[id] = c[id] || {}
      depositAmount = c[id]['depositAmount'] || depositAmount || 0;
      withdrawalAmount = c[id]['withdrawalAmount'] || withdrawalAmount || 0;
      c[id] = ({ id, depositAmount, withdrawalAmount, ...rest });
      return c;
    },
    {})
  )
  
console.log(transactions)
.as-console-wrapper { max-height: 100% !important; top: 0 }

如果您想同时按 iduser 进行分组,您需要从两个值中创建结果对象键,并由一个不在其中任何一个中的字符连接(例如# 适用于您的数据):

const withdrawal = [{
    "id": "a1",
    "withdrawalAmount": 300,
    "user": "John"
  },
  {
    "id": "b2",
    "withdrawalAmount": 100,
    "user": "Mike"
  }
]

const deposit = [{
    "id": "a2",
    "depositAmount": 123,
    "user": "John"
  },
  {
    "id": "b2",
    "depositAmount": 109,
    "user": "Mike"
  },
  {
    "id": "c3",
    "depositAmount": 44,
    "user": "John"
  }
]

const transactions = Object.values(
  withdrawal
    .concat(deposit)
    .reduce((c, { id, user, depositAmount, withdrawalAmount, ...rest }) => {
      key = `${id}#${user}`
      c[key] = c[key] || {}
      depositAmount = c[key]['depositAmount'] || depositAmount || 0;
      withdrawalAmount = c[key]['withdrawalAmount'] || withdrawalAmount || 0;
      c[key] = ({ id, user, depositAmount, withdrawalAmount, ...rest });
      return c;
    },
    {})
  )
  
console.log(transactions)
.as-console-wrapper { max-height: 100% !important; top: 0 }

下面介绍的是实现所需 objective.

的一种可能方法

代码段

// helper method to obtain all props 
// from array-elt matching "id"
const getInfo = (ar, argId) => (
  ar?.find(({ id }) => id === argId) ?? {}
);

// combine both arrays using "id"
const combineArrays = (ar1, ar2) => {
  // first get unique ids combining both arrays
  const uniqIds = [
    ...new Set(
      [...ar1, ...ar2]
      .map(({ id }) => id)
    )
  ];
  // now, for each unique id
  // simply get relevant info from both
  // arrays where element's match the "id"
  return uniqIds.map(id => ({
    id,
    ...getInfo(ar1, id),
    ...getInfo(ar2, id)
  }));
};

const withdrawal = [{
    "id": "a1",
    "withdrawalAmount": 300,
    "user": "John"
  },
  {
    "id": "b2",
    "withdrawalAmount": 100,
    "user": "Mike"
  }
];

const deposit = [{
  "id": "a1",
  "depositAmount": 123,
  "user": "John"
}];

// invoke the method and display the result
console.log(
  'combined both arrays as below:\n',
  combineArrays(withdrawal, deposit)
);
.as-console-wrapper { max-height: 100% !important; top: 0 }

说明

在上面的代码段中添加了内联评论。

const withdrawal = [{
    "id": "a1",
    "withdrawalAmount": 300,
    "user": "John"
  },
  {
    "id": "b2",
    "withdrawalAmount": 100,
    "user": "Mike"
  }
]


const deposit = [{
  "id": "a1",
  "depositAmount": 123,
  "user": "John"
}, ]
const mergeArr = withdrawal.map(ele => {
  let other = deposit.find(({id}) => id === ele.id)
  return other ? {...ele, ...other} : {...ele, depositAmount : 0}
})
console.log(mergeArr)

在第一次迭代中仅合并公共对象,然后 re-iterate 两个数组并在最终数组中仅取 un-used 项。

class Transaction {
  constructor(transaction) {
    this.id = transaction.id;
    this.depositAmount = transaction.depositAmount | 0;
    this.withdrawAmount = transaction.withdrawalAmount | 0;
    this.user = transaction.user;
  }
}

let withdrawl = [
  {
    id: "a1",
    withdrawalAmount: 300,
    user: "John",
  },
  {
    id: "b2",
    withdrawalAmount: 100,
    user: "Mike",
  },
  {
    id: "c3",
    withdrawalAmount: 33,
    user: "John",
  },
];

let deposit = [
  {
    id: "a1",
    depositAmount: 123,
    user: "John",
  },
  {
    id: "c3",
    depositAmount: 44,
    user: "John",
  },
];


let transactions = [];

// merge the common key of two array into one array
withdrawl.forEach((item1) => {
  deposit.forEach((item2) => {
    if (item1.id === item2.id) {
      let combined = { ...item1, ...item2 };
      let transaction = new Transaction(combined);
      transactions.push(transaction);

      // mark the item as used
      // or set some flag to know
      // the item is used in the array
      item1.used = true;
      item2.used = true;
    }
  })
})

// now take all the unused item from the both array
// and push them to the transactions array
withdrawl.forEach((item1) => {
  if (!item1.used) {
    let transaction = new Transaction(item1);
    transactions.push(transaction);
  }
});

deposit.forEach((item2) => {
  if (!item2.used) {
    let transaction = new Transaction(item2);
    transactions.push(transaction);
  }
});

console.log(transactions);


对于大型阵列,请使用 Nick 的 (最后你会节省很多周期)

对于数组中的少量项,find() 的解决方案就足够了:

const withdrawal= [
    {
        "id": "a1",
        "withdrawalAmount": 300,
        "user": "John"
    },
    {
        "id": "b2",
        "withdrawalAmount": 100,
        "user": "Mike"
    },
    {
        "id": "c3",
        "withdrawalAmount": 33,
        "user": "John"
    }
]


const deposit= [
    {
        "id": "a1",
        "depositAmount": 123,
        "user": "John"
    },
    {
        "id": "c3",
        "depositAmount": 44,
        "user": "John"
    }
]

const transactions = withdrawal.map(item => ({"depositAmount": 0, ...item}));

deposit.forEach( item => {
  const found = transactions.find(x => x.id === item.id);
  if (found) {
      Object.assign(found,item);
  } else {
    transactions.push(Object.assign(item,{"withdrawalAmount": 0}));
  }
  });


console.log(transactions)

注意:此代码假定您想要两个数组的并集而不是交集