首页 > 解决方案 > 根据匹配的 ID 合并两个数组中的项目

问题描述

我有一个这样的数据对象:

{
  "data1": [
    [
      "ID",
      "name",
      "Birthday"
    ],
    [
      "10",
      "thomas",
      "1992-03-17"
    ],
    [
      "11",
      "Emily",
      "2000-03-03"
    ]
  ],
  "data2": [
    [
      "Balance",
      "ID"
    ],
    [
      "$4500",
      "10"
    ],
    [
      "$1500",
      "13"
    ]
  ]
}

它包含两个数组data1data2. 每个数组中的第一行是列的名称,其余行包含数据(将其视为表格)。

我想比较ID两个数组中的字段,如果IDs 匹配,则最终输出将包含一列Balance,其中余额对应于该列ID,如果IDs 不匹配,Balance则将是$0

预期输出:

{
  "output": [
    [
      "ID",
      "name",
      "Birthday",
      "Balance"
    ],
    [
      "10",
      "thomas",
      "1992-03-17",
      "$4500" //ID 10 matched so the balance added here
    ],
    [
      "11",
      "Emily",
      "2000-03-03",
      "0" //0 bcoz the ID 11 is not there in data2 array
    ]
  ]

}

我觉得这很难完成。把它想象成 MySQL 中的 LEFT-JOIN。我提到了这个解决方案,但它在我的情况下不起作用,因为我的回复中没有密钥。

编辑:我也需要加入其他领域。

标签: javascriptarraysnode.jssortingleft-join

解决方案


您可以使用Array.prototype.map()findfilterslicereduceconcatincludesObject.assign()

这个解决方案:

  • 处理项目的任意顺序。订单从标题中读取。
  • Balance仅当 中存在一个字段时才附加一个字段data2
  • 加入所有其他领域(由 OP 要求,请参阅下面的评论)
  • data1如果数据不存在于和中,则将默认值作为输入并使用它们data2

function merge({ data1, data2 }, defaults) {
  // get the final headers, add/move 'Balance' to the end
  const headers = [...data1[0].filter(x => x !== 'Balance')]
    .concat(data2[0].includes('Balance') ? ['Balance'] : []);
  
  // map the data from data1 to an array of objects, each key is the header name, also merge the default values.
  const d1 = data1.slice(1)
    .map(x => x.reduce((acc, y, i) => ({ ...defaults, ...acc, [data1[0][i]]: y }), {}));
  // map the data from data2 to an array of objects, each key is the header name
  const d2 = data2.slice(1)
    .map(x => x.reduce((acc, y, i) => ({ ...acc, [data2[0][i]]: y }), {}));
  
  // combine d1 and d2
  const output = d1.map((x, i) => { // iterate over d1
    // merge values from d2 into this value
    const d = Object.assign(x, d2.find(y => y['ID'] === x['ID']));
    // return an array ordered according to the header
    return headers.map(h => d[h]);
  });
  return { output: [headers, ...output] };
}

const test0 = {
  data1: [[ "ID","name","Birthday","other"],["10","thomas","1992-03-17","empty"],["11","Emily","2000-03-03","empty"]],
  data2: [["other", "ID", "Balance", "city"],["hello", "10", "$4500", "New York"],["world", "10","$8","Brazil"]]
};

const test1 = {
  data1: [["ID","name","Birthday"],["10","thomas","1992-03-17"],["11","Emily","2000-03-03"]],
  data2: [["other","ID"],["x","10"],["y","11"]]
};

console.log(merge(test0, { Balance: '$0' }));
console.log(merge(test1, { Balance: '$0' }));


推荐阅读