Javascript разобрать файл Excel и создать декартово произведение - PullRequest
0 голосов
/ 19 июня 2020

У меня есть файл Excel, содержащий два листа. Один из них - это лист source, содержащий список идентификаторов. Второй лист - это данные с тремя столбцами.

Я пытаюсь проанализировать этот документ и создать декартово произведение из двух листов. Для каждого идентификатора на листе source его необходимо объединить с каждой строкой на листе data.

Пример:

Лист 1 (Источник ):

ABC
DEF
GHI

Лист 2 (Данные):

Bob, 20, Arizona
James, 30, California
Sam, 40, Florida

Ожидаемый результат:

Bob, 20, Arizona, ABC
James, 30, California, ABC
Sam, 40, Florida, ABC

Bob, 20, Arizona, DEF
James, 30, California, DEF
Sam, 40, Florida, DEF

Bob, 20, Arizona, GHI
James, 30, California, GHI
Sam, 40, Florida, GHI

Я использую nodejs для синтаксического анализа этого файла xlsx и перебирать листы. Я получаю два массива, каждый с правильными данными, которые выглядят следующим образом.

[
  { SourceId: 'ABC' },
  { SourceId: 'DEF' },
  { SourceId: 'GHI' }
]
[
  { Name: 'Bob', Age: 20, Location: 'Arizona' },
  { Name: 'James', Age: 30, Location: 'California' },
  { Name: 'Sam', Age: 40, Location: 'Florida' }
]

Теперь я пытаюсь объединить два массива, где каждая строка данных сопоставляется с каждой строкой в ​​источнике. В моем примере есть 3 строки данных и 3 идентификатора источника. Это могло бы дать результат 9.

Если бы это были оба массива, все было бы просто, но мне сложно понять, как добавить их к объекту данных.

Код:

var XLSX = require("xlsx");
var workbook = XLSX.readFile("data.xlsx");
var sheet_name_list = workbook.SheetNames;

sheet_name_list.forEach(function (y) {
  var worksheet = workbook.Sheets[y];
  var worksheetName = y;
  var headers = {};
  var data = [];
  var primarySet = [];

  for (z in worksheet) {
    if (z[0] === "!") continue;

    //parse out the column, row, and value
    var col = z.substring(0, 1);
    var row = parseInt(z.substring(1));
    var value = worksheet[z].v;

    //store header names
    if (row == 1) {
      headers[col] = value;
      continue;
    }

    if (worksheetName == "Source") {
      if (!primarySet[[row]]) {
        primarySet[row] = {};
      }
      primarySet[row][headers[col]] = value;
    }

    if (!data[row]) {
      data[row] = {};
    }
    data[row][headers[col]] = value;

  }
  //drop those first two rows which are empty
  data.shift();
  data.shift();
  console.log(data);

  /* Expected Output

  [
    { Name: 'Bob', Age: 20, Location: 'Arizona', SourceId: 'ABC' },
    { Name: 'James', Age: 30, Location: 'California', SourceId: 'ABC' },
    { Name: 'Sam', Age: 40, Location: 'Florida', SourceId: 'ABC' },

    { Name: 'Bob', Age: 20, Location: 'Arizona', SourceId: 'DEF' },
    { Name: 'James', Age: 30, Location: 'California', SourceId: 'DEF' },
    { Name: 'Sam', Age: 40, Location: 'Florida', SourceId: 'DEF' },

    { Name: 'Bob', Age: 20, Location: 'Arizona', SourceId: 'GHI' },
    { Name: 'James', Age: 30, Location: 'California', SourceId: 'GHI' },
    { Name: 'Sam', Age: 40, Location: 'Florida', SourceId: 'GHI' },

]

   */

});

Есть ли хороший способ справиться с этим, где я могу по существу объединить источник с данными n раз?

1 Ответ

2 голосов
/ 19 июня 2020

Как насчет использования flatMap для получения ожидаемого результата:

var arr1 = [ { SourceId: 'ABC' }, { SourceId: 'DEF' }, { SourceId: 'GHI' }];
var arr2 = [ { Name: 'Bob', Age: 20, Location: 'Arizona' }, { Name: 'James', Age: 30, Location: 'California' }, { Name: 'Sam', Age: 40, Location: 'Florida' }];

var result = arr1.flatMap(({SourceId},i)=>arr2.map(val=>({...val, SourceId})));

console.log(result)
...