Столбец суммы в потоке с использованием узла

Моя цель - подсчитать сумму столбца, который соответствует другому столбцу в CSV.

Например, у меня есть вход CSV, который выглядит так

"500","my.jpg"
"500","my.jpg"
"200","another.jpg"

Я хочу, чтобы вывод был:

[{ bytes: 1000, uri: "my.jpg" }, { bytes:200, "another.jpg" }]

Примечание: мне нужно сделать это как поток, так как для данного csv может быть более 3 миллионов записей, а зацикливание слишком медленное.

Мне удалось сделать это с помощью awk но я изо всех сил, чтобы реализовать это в узле

Вот скрипт bash, использующий awk команда

awk -F, 'BEGIN { print "["}
{   
    gsub(/"/, ""); # Remove all quotation from csv
    uri=$2; # Put the current uri in key
    a[uri]++; # Increment the count of uris
    b[uri] = b[uri] + $1; # total up bytes
} 
END { 
    for (i in a) {
        printf "%s{\"uri\":\"%s\",\"count\":\"%s\",\"bytes\":\"%s\"}",
        separator, i, a[i], b[i]
        separator = ", "
    }

    print "]"
}
' ./res.csv

любые указатели в правильном направлении будут с благодарностью

2 ответа

Решение

Вы можете попробовать создать поток чтения для вашего CSV-файла и передать его в синтаксический анализатор CSV-Streamify.

const csv = require('csv-streamify')
const fs = require('fs')

const parser = csv()
const sum = {};

// emits each line as a buffer or as a string representing an array of fields
parser.on('data', function (line) {
  let key = line[1];
  let val = line[0];
  if (!sum[key]) {
    sum[key] = 0;
  }
  sum[key] = sum[key] + parseInt(val);
  console.log("Current sum for " + key + ": " + sum[key])
})

parser.on('end', function () {
  let results = Object.keys(sum)
    .map(key => ({ bytes: sum[key], uri: key }))
  console.log(results);
})

// now pipe some data into it
fs.createReadStream('./test.csv').pipe(parser)

Используя ваш пример данных, этот пример должен напечатать:

[ { bytes: 1000, uri: 'my.jpg' },
  { bytes: 200, uri: 'another.jpg' } ]

Вы также можете попробовать приведенное ниже решение Perl.

$ cat url.txt
"500","my.jpg"
"500","my.jpg"
"200","another.jpg"
"600","more.jpg"

$ perl -lne ' if(/\"(\d+)\",\"(.+?)\"/g) { $kv{$2}+=$1} ; END { print "["; for(keys %kv) { print "$s { bytes:$kv{$_} uri:\"$_\" } ";$s="," } print "]" } ' url.txt
[
 { bytes:600 uri:"more.jpg" }
, { bytes:200 uri:"another.jpg" }
, { bytes:1000 uri:"my.jpg" }
]

$
Другие вопросы по тегам