Поэтому у меня есть файл laaaaaaaarge:
Item|Cost1|Cost2
Pizza|50|25
Sugar|100|100
Spices|100|200
Pizza|100|25
Sugar|200|100
Pizza|50|100
Я хочу добавить все Cost1
и Cost2
для определенного элемента и создать объединенный вывод.
Я написал код python для этого,
item_dict = {}
for line in file:
fields = line.split('|')
item = fields[0]
cost1 = fields[1]
cost2 = fields[2]
if item_dict.has_key(item):
item_dict[item][0] += int(cost1)
item_dict[item][1] += int(cost2)
else:
item_dict[item] = [int(cost1),int(cost2)]
for key, val in item_dict.items():
print key,"|".join(val)
Есть ли способ сделать это очень эффективно и быстро в awk или с помощью любого другого волшебства?
Или я могу сделать свой python более элегантным и быстрым?
Ожидаемый результат
Pizza|200|150
Sugar|300|200
Spices|100|200
Что-то вроде этого...
$ awk 'BEGIN{OFS=FS="|"}
NR>1 {cost1[$1]+=$2; cost2[$1]+=$3}
END{ for (i in cost1) print i, cost1[i], cost2[i]}' file
Sugar|300|200
Spices|100|200
Pizza|200|150
BEGIN{OFS=FS="|"}
устанавливает разделитель полей ввода и вывода как |
,NR>1
означает, что мы будем делать некоторые действия для номера строки, большего, чем 1. Таким образом мы пропускаем заголовок.cost1
и cost2
- это массивы, индекс которых является первым полем, а его значение представляет собой сумму до этой точки.END {}
- это то, что мы делаем после прочтения всего файла. Он состоит в прокрутке массива и печати значений.awk '
BEGIN { FS=OFS="|" }
NR==1 { expectedNF = NF; next }
NF != expectedNF { print "Fix your #%@#&! data, idiot!"; exit 1 }'
{
items[$1]
for (c=2;c<=NF;c++)
cost[$1,c] += $c
}
END {
for (i in items) {
printf "%s", i
for (c=2;c<=NF;c++)
printf "%s%s", OFS, cost[i,c]
print ""
}
}
' file
Не стесняйтесь сжимать его на 1 или 2 линии по своему усмотрению.
На практике я бы сделал то, что сделал fedorqui. Для полноты, однако, этот скрипт python
должен быть быстрее вашего оригинала:
#!/usr/bin/env python
import fileinput
item_dict = {}
for line in fileinput.input():
if not fileinput.isfirstline():
fields = line.strip().split('|')
item = fields[0]
cost1 = int(fields[1])
cost2 = int(fields[2])
try:
item_dict[item][0] += cost1
item_dict[item][1] += cost2
except KeyError:
item_dict[item] = [cost1, cost2]
for key, val in item_dict.items():
print "%s|%s|%s" % (key,val[0],val[1])
Сохраните сценарий в файле, таком как sumcols
и сделайте его исполняемым chmod +x sumcols
и запустите как:
$ ./sumcols file
Spices|100|200
Sugar|300|200
Pizza|200|150