【问题标题】:Merging arrays of objects from different CSVs合并来自不同 CSV 的对象数组
【发布时间】:2019-01-09 16:15:21
【问题描述】:

我正在使用 D3JS 来可视化 Jenkins 收集的数据。唯一的问题是我想同时可视化多行,而为这些创建 CSV 文件的 Jenkins 脚本正在创建多个单独的文件。例如:

文件1:

ID;ValueA;ValueB
ID01;10;10
ID02;30;40

文件2:

ID;ValueC;ValueD
ID01;20;30
ID03;50;60

这样合并后的最终结果应该是这样的:

ID;ValueA;ValueB;ValueC;ValueD
ID01;10;10;20;30
ID02;30;40;;
ID03;;;50;60

我的问题是 concat 只是做了以下事情:

ID01;10;10
ID02;30;40
ID01;20;30
ID03;50;60

【问题讨论】:

  • 您的问题并不完全清楚:您是想将 CSV 合并到一个新的 CSV 中,还是要合并解析两个 CSV 后创建的对象数组?
  • 对不起,你是对的。我想合并 d3.csv 解析的数组

标签: javascript html csv d3.js


【解决方案1】:

有几种方法可以合并这些对象数组,这些方法可以提高速度、简洁性或可读性等...

这是几种方法中的一种。首先,让我们获取解析后的 CSV。由于我不能在 * sn-p 中使用真正的 CSV,我将使用模板文字;另外,由于您的 CSV 中有分号,我将使用 DSV 解析器:

const file1 = `ID;ValueA;ValueB
ID01;10;10
ID02;30;40`;

const file2 = `ID;ValueC;ValueD
ID01;20;30
ID03;50;60`;

const csv1 = d3.dsvFormat(";").parse(file1);
const csv2 = d3.dsvFormat(";").parse(file2);

现在我们根据 CSV 获取标题:

const headers = [...new Set(csv1.columns.concat(csv2.columns))].filter(function(d) {
  return d !== "ID"
});

函数终于来了:

const mergedData = [];

csv1.concat(csv2).forEach(function(row) {
  const foundObject = mergedData.find(function(d) {
    return d.ID === row.ID
  });
  if (foundObject) {
    headers.forEach(function(d) {
      if (row[d]) foundObject[d] = row[d];
    });
  } else {
    headers.forEach(function(d) {
      if (!row[d]) row[d] = "";
    });
    mergedData.push(row)
  };
});

我们首先为合并的数据创建一个空数组。然后,我们在该数组中搜索与两个 CSV 中每个对象的 ID 匹配的对象:如果找到,则创建额外的列;如果未找到原始行,则推送原始行,并将 "" 作为它没有的列的值,这正是 d3.csv() 所做的。

这里是演示:

const file1 = `ID;ValueA;ValueB
ID01;10;10
ID02;30;40`;

const file2 = `ID;ValueC;ValueD
ID01;20;30
ID03;50;60`;

const csv1 = d3.dsvFormat(";").parse(file1);
const csv2 = d3.dsvFormat(";").parse(file2);

const headers = [...new Set(csv1.columns.concat(csv2.columns))].filter(function(d) {
  return d !== "ID"
});

const mergedData = [];

csv1.concat(csv2).forEach(function(row) {
  const foundObject = mergedData.find(function(d) {
    return d.ID === row.ID
  });
  if (foundObject) {
    headers.forEach(function(d) {
      if (row[d]) foundObject[d] = row[d];
    });
  } else {
    headers.forEach(function(d) {
      if (!row[d]) row[d] = "";
    });
    mergedData.push(row)
  };
});

console.log(mergedData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

【讨论】: