Я бы разбил это на два шага. Сначала мы анализируем CSV, чтобы получить массив объектов. Затем мы перебираем их, чтобы найти статистику, такую как minVal
и minRow
(и любые другие, которые нам могут понадобиться.) Хотя это немного менее эффективно, чем делать это за один проход, это приводит к более простому, более поддерживаемому коду.
Итак, у нас есть csv2arr
, который преобразует вашу CSV-строку в объекты, которые выглядят следующим образом:
{
date: "31/10/2019",
open: 9202.457589,
high: 9383.160892,
low: 9028.71744,
close: 9199.584833
}
и stats
, который принимает массив таких объектов для поиска такой статистики как maxVal
и minRow
для каждого столбца. Мы могли бы улучшить это, чтобы найти другие характеристики, такие как mean
и median
при желании. Его вывод выглядит так:
{
date: { /* ... */ },
open: { /* ... */ },
high: { /* ... */ },
low: { /* ... */ },
close: {
minVal: 9199.584833,
maxVal: 9427.687584,
minRow: {date: "31/10/2019", open: 9202.457589, high: 9383.160892, low: 9028.71744, close: 9199.584833},
maxRow: {date: "29/10/2019", open: 9248.440562, high: 9516.181048, low: 9232.648086, close: 9427.687584}
}
}
Это один из способов сделать это:
// Naive, but useful for some data
const csv2arr = (csv) => {
const [headers, ...rows] = csv .trim () .split ('\n') .map (r => r .split (','))
return rows .reduce ((a, r) => [
... a,
Object .assign (... (r .map ((c, i) => ({[headers [i]]: isNaN(c) ? c : Number(c)}))))
], [])
}
const stats = (rows) => rows .reduce (
(stats, row) => Object .assign (
... Object .entries (row) .map (([key, val]) => ({[key]: ({
minVal: key in stats && stats [key] .minVal < val ? stats [key] .minVal : val,
maxVal: key in stats && stats [key] .maxVal > val ? stats [key] .maxVal : val,
minRow: key in stats && stats [key] .minRow [key] < val ? stats [key] .minRow : row,
maxRow: key in stats && stats [key] .maxRow [key] > val ? stats [key] .maxRow : row,
})}))
),
{}
)
const csv = `
date,open,high,low,close
31/10/2019,9202.457589,9383.160892,9028.71744,9199.584833
30/10/2019,9422.463325,9426.874217,9085.370357,9205.726559
29/10/2019,9248.440562,9516.181048,9232.648086,9427.687584
28/10/2019,9565.101883,9805.118089,9256.148389,9256.148389
`
const rows = csv2arr (csv)
const statistics = stats (rows)
console .log (rows)
console .log (statistics)
Обратите внимание, что минимальные / максимальные значения для дат здесь не имеют большого смысла. Если бы они были в формате ISO (например, «2019-10-31»), то эти значения также получили бы значимые максимумы и минимумы.
csv2arr
полезно для достаточно широкого диапазона случаев. Но не принимайте это за полный анализатор CSV. Например, если ваши данные содержат ячейки с запятыми, произойдет сбой. Это также наивно о выходе. По сути, если оно выглядит как число, оно становится числом, даже если другие вещи в столбце не совпадают. Есть и другие проблемы. Но это все еще полезно для многих форматов, разделенных запятыми.