在文件linux中每行下面的总和行

时间:2014-11-11 19:36:15

标签: python linux bash

我有这样的输入

A  100
B  150
C  200
D  250
E  300

我想要的输出是上面所有元素的总和:像这样的东西

   A to A - 100
   A to B - 250
   A to C - 450
   A to D - 700
   A to E - 1000
   B to B - 150
   B to C - 350
   B to D - 600
   B to E - 900
   C to C - 200
   C to D - 450
   C to E - 650
   D to D - 250
   D to E - 550
   E to E - 300

文件大小约为250 MB。我写了一个python程序,它首先在字典中存储每行。但我认为这对大型投入来说是不可行的。我是初学者,使用linux。

5 个答案:

答案 0 :(得分:1)

这只是存储值和嵌套循环的问题:

awk '
    { label[NR]=$1; val[NR]=$2 } 
    END {
        for (i=1; i<=NR; i++) {
            sum = 0
            for (j=i; j<=NR; j++) {
                sum += val[j]
                print label[i] " to " label[j] " - " sum
            }
        }
    }
' file

我认为对于大文件来说这仍然会很慢(你必须将整个文件存储在内存中,并且它是O(N ^ 2)(或者是O(NlogN),它已经有一段时间......)执行嵌套循环的操作。我怀疑将数据丢入数据库可以帮助你。

答案 1 :(得分:1)

所以你的输入文件大约是250MB。我们称之为250MB或262144000字节。您的代表输入是每行7个字节 - 单个字符,两个空格,三位数字和换行符。这意味着大约有3479142个单独的行。

如果你的目的是最终为输入文件中的每一对可能的行生成输出,就像它似乎那样,那么你需要准备好存储3479142 * 37449143/2 = 701219136992653单独的输出行。代表每个代表7个字节,并忽略了大多数可能会更大的事实,即4908533958948571字节,或者您需要存储的4464太字节数据。

希望您的预算有足够的资金支持几个大型EMC阵列。否则,正如你所怀疑的那样,这可能只是在一个不可行的方面......

答案 2 :(得分:0)

使用python:

>>> value =[]
>>> name = []
>>> f=open('yourfile.txt')
>>> for x in f:
...     x=x.strip()
...     na,va = x.split()
...     name.append(na)
...     value.append(va)
... 
>>> name
['A', 'B', 'C', 'D', 'E']
>>> value
['100', '150', '200', '250', '300']
>>> for i in range(len(name)):
...     for j in range(i,len(name)):
...         print name[i],name[j],str(sum(map(int,value[i:j+1])))
... 

输出:

A A 100
A B 250
A C 450
A D 700
A E 1000
B B 150
B C 350
B D 600
B E 900
C C 200
C D 450
C E 750
D D 250
D E 550
E E 300

答案 3 :(得分:0)

在Python中,您可以使用itertools.combinations_with_replacementcollections.OrderedDict执行此操作。这里存储在内存中的唯一东西是一个字典,第一列中的项目作为键,第二列中的项目作为值:

from itertools import combinations_with_replacement
from collections import OrderedDict

with open('file.txt') as f:
    data = OrderedDict((k, int(v)) for k, v in (line.split() for line in f))
    start = None
    tot = 0
    for k1, k2 in combinations_with_replacement(data.iterkeys(), 2):
        if k1 != start:
            start = k1
            tot = data[k1]
            print '{} to {} - {}'.format(k1, k2, tot)
        else:
            tot += data[k2]
            print '{} to {} - {}'.format(k1, k2, tot)

<强>输出:

A to A - 100
A to B - 250
A to C - 450
A to D - 700
A to E - 1000
B to B - 150
B to C - 350
B to D - 600
B to E - 900
C to C - 200
C to D - 450
C to E - 750
D to D - 250
D to E - 550
E to E - 300

答案 4 :(得分:-1)

这是一个快速的:

awk '{s+=$2; printf("%s - %d\n", $1, s)}' <your-file>

如果你想打印A to A, A to B等,我们将不得不变得更加花哨:

(在tcsh中)

foreach n (`seq 5 -1 1`)
tail -$n <your-file> | awk '{s+=$2; if (a) NR; else{ a=$1;} printf("%s to %s - %d\n", a, $1, s);}'
end

示例输出:

A - 100
B - 250
C - 450
D - 700
E - 1000
B to B - 150
B to C - 350
B to D - 600
B to E - 900
C to C - 200
C to D - 450
C to E - 750
D to D - 250
D to E - 550
E to E - 300