0

我正在使用Node 的 CSV 包来解析项目中的一些 CSV 文件。我需要能够处理有和没有标题的案例。所以:

const withHeader = `h1,h2,h3
d1a,d2a,d3a
d1b,d2b,d3b`;

const withoutHeader = `d1a,d2a,d3a
d1b,d2b,d3b`;

我的应用程序不知道列数及其名称。它们要么从标题中读取,要么应该以数字方式生成,例如col0,col1,col2.

这是我遇到问题的地方。我总是希望csvParse的输出采用对象文字形式。当最终用户指示 CSV 具有标题时,这很容易:

> csvParse(withHeader, {columns: true})
[
  { h1: 'd1a', 'h2': 'd2a', 'h3': 'd3a' },
  { h1: 'd1b', 'h2': 'd2b', 'h3': 'd3b' }
]

但是,当用户指出没有标题行时,似乎不可能以对象文字形式使用程序生成的列标题来结束数据。

的 3 个选项columnsboolean | array | function

  • 通过提供false,返回的数据是一个数组数组,然后我需要将其转换为对象文字形式。不理想!
  • 要提供列名数组,我已经需要知道有多少列......在解析之前,这是没有意义的。我可以解析第一行以获取计数,然后重新开始提供数组,但这似乎很笨拙。
  • 我可以提供一个以编程方式生成列键的函数。例如column => column,这无济于事,因为 a) 没有提供索引,并且 b) 然后忽略第一行,因为它被假定为将列标题转换为所需的列键。

有没有我错过的方法来做到这一点?以下是两种看似笨拙且效率较低的方法。

解析 1 行,然后解析所有

// Obviously in actual use I'd handle edge cases
const colCount = csvParse(withoutHeader, {to_line: 1})[0].length;
// 3
const data = csvParse(withoutHeader, {columns: [...Array(colCount).keys()].map(i => `col{i}`)})
/*
[
  { col0: 'd1a', col1: 'd2a', col2: 'd3a' },
  { col0: 'd1b', col1: 'd2b', col2: 'd3b' }
]
*/

解析成数组数组,然后转换

csvParse(withoutHeader).map(
  row => row.reduce(
    (obj, item, index) => {
      obj[`col${index}`] = item;
      return obj;
    },
    {}
  )
)
/*
[
  { col0: 'd1a', col1: 'd2a', col2: 'd3a' },
  { col0: 'd1b', col1: 'd2b', col2: 'd3b' }
]
*/

对我来说,能够指定columns为一个函数是理想的,它被赋予列索引作为参数而不是标题行。

4

0 回答 0