如何将带有嵌套对象的数组对象转换为CSV文件

时间:2019-06-09 03:11:19

标签: javascript arrays object ecmascript-6 export-to-csv

我需要一些帮助。我想按图1所示排列数组嵌套对象,并将数据获取到array2D以便将数据保存到CSV文件,但是我不太了解如何循环数据以获取详细信息到array2D。或其他任何人都可以通过这种方式将数据导出到CSV文件中。


图1:

var data = {
  deviceA: {
    smokeSensor: [
      {
        '190501': {
          '0001': 200,
          '0002': 300
        },
      },
      {
        '190502': {
          '0001': 20,
          '0002': 30
        },
      }
    ],
    fireSensor: [
      {
        '190501': {
          '0001': 700,
          '0002': 750
        },
      },
      {
        '190502': {
          '0001': 780,
          '0002': 630
        },
      }
    ]
  },
  deviceB: {
    smokeSensor: [
      {
        '190601': {
          '0001': 100,
          '0002': 110
        },
      },
      {
        '190602': {
          '0001': 120,
          '0002': 130
        },
      }
    ],
    fireSensor: [
      {
        '190601': {
          '0001': 600,
          '0002': 522
        },
      }
    ]
  },
};

这是我想与array2D一起获得的输出,以将其转换为将array2D转换为CSV文件的功能。

const rows = [
  ["DeviceA"]
  ["Date/Time", "smokeSensor", "fireSensor"],
  ["190501 00:01", "200", "700"],
  ["190501 00:02", "300", "750"],
  ["190502 00:01", "20", "780"],
  ["190502 00:02", "30", "630"],
  [""],
  ["DeviceB"],
  ["Date/Time", "smokeSensor", "fireSensor"],
  ["190501 00:01", "100", "600"],
  ["190501 00:02", "110", "522"],
  ["190502 00:01", "120", ""],
  ["190502 00:02", "130", ""],
];

这是我尝试循环的代码,但是一旦循环每个循环以获取日期时间的每个值细节,我都会感到茫然。不幸的是,我得到的细节不是所期望的。

var dataCSV = []
var mdbName = []
var header = ['DateTime']
var content = []
var dateTime = ''
for (var deviceId in data) {
  mdbName.push(deviceId)
  for (var sensorName in data[deviceId]) {
    header.push(sensorName)
    // console.log(data[deviceId][sensorName]);
    Object.keys(data[deviceId][sensorName]).forEach(item => {
      let date = data[deviceId][sensorName][item]
      for (var key3 in date) {
        // console.log(key3)
        for (var key4 in date[key3]) {
          dateTime = key3 + key4
          // console.log(deviceId + ': ' + sensorName + ': ' + dateTime + ':' + date[key3][key4])
          content.push(date[key3][key4])
        }
      }
    })
  }
}
dataCSV.push(mdbName)
dataCSV.push(header)
dataCSV.push(content)
console.log('End: ', dataCSV)

这是我的错误输出:

[ 
  [ 'deviceA', 'deviceB' ],
  [ 'DateTime', 'smokeSensor', 'fireSensor', 'smokeSensor', 'fireSensor' ],
  [ 200, 300, 20, 30, 700, 750, 780, 630, 100, 110, 120, 130, 600, 522 ] 
]

1 个答案:

答案 0 :(得分:0)

您可以使用以下功能。方法是遍历结构的键,按时间和时/分字符串对传感器值进行分组,并将每个设备转储到结果行中。根据您的规范,进行了一些填充以确保行的宽度相同。

进行一些清理不会有什么坏处,但是似乎可以完成工作(我假设您的DeviceB输出是"190501"上的错字,根据您的输入数据应该是"190601"

var data = { deviceA: { smokeSensor: [ { '190501': { '0001': 200, '0002': 300 }, }, { '190502': { '0001': 20, '0002': 30 }, } ], fireSensor: [ { '190501': { '0001': 700, '0002': 750 }, }, { '190502': { '0001': 780, '0002': 630 }, } ] }, deviceB: { smokeSensor: [ { '190601': { '0001': 100, '0002': 110 }, }, { '190602': { '0001': 120, '0002': 130 }, } ], fireSensor: [ { '190601': { '0001': 600, '0002': 522 }, } ] }, };

const dataToCSV = data => {
  const rows = [];

  for (const device in data) {
    rows.push(
      [device.replace(/^./, m => m.toUpperCase())], 
      ["Date/Time", ...Object.keys(data[device])]
    );
    const groups = {};
    let longest = 0;

    for (const sensor in data[device]) {  
      for (const time of data[device][sensor]) {
        const k = Object.keys(time)[0];

        for (const hm in time[k]) {
          const groupKey = `${k} ${hm.replace(/(\d\d)(\d\d)/, "$1:$2")}`;

          if (!(groupKey in groups)) {
            groups[groupKey] = [groupKey];
          }

          groups[groupKey].push("" + time[k][hm]);
          longest = Math.max(longest, groups[groupKey].length);
        }
      }
    }

    for (const group of Object.values(groups)) {
      while (group.length < longest) { 
        group.push("");
      }

      rows.push(group);
    }

    rows.push([""]);
  }

  return rows.slice(0, -1);
};

console.log(dataToCSV(data));