使用python比较单个文件中的行

时间:2013-11-20 17:39:16

标签: python loops python-2.7

我有一个文本文件,其中包含空格分隔数据,如下所示:

aaa bbb 10
aaa bbb 5
aaa bbb 6
aaa bbb 2
aaa ccc 4
aaa ccc 11
aaa ccc 7
aaa ddd 9
aaa ddd 13
aaa ddd 12
aaa ddd 19
xxx yyy 20
xxx yyy 4
xxx yyy 6
xxx yyy 8
xxx yyy 12
xxx zzz 10
xxx zzz 11
xxx zzz 4
xxx zzz 5
xxx zzz 6

我不确定如何用文字解释这个,但我想把具有最大数值的行写到一个单独的文件中。

输出应如下所示:

aaa bbb 10
aaa ccc 11
aaa ddd 19
xxx yyy 20
xxx zzz 11

这是我尝试过的一些代码,但没有用过

for line in r.readlines()[1:]:
    z = re.split(' ', line)
    a = []
    a.append(z)
    for i in xrange(len(a)):
        if z[0] == a[i][0] and z[1] == a[i][1]:
            if z[7] > a[i][7]:
               del a[i]
               a.append(z)
    for x in a:
    p.write(' '.join(x))

我最初没有在问题中明确说明(我试图不提供有关我正在使用的数据的太多信息),但是在这个文件中有8个“列”。前三个是字母数字,第四个是整数,后四个是浮点数。我需要使用最后一列(浮点数)作为最大值。对此抱歉!

另一种解决方案

allLines = r.readlines()

bestOf = re.split(' ', allLines[1])

f = open("results_filtered.txt", 'a')
for line in allLines[2:]:
   z = re.split(' ', line)
   if z[0] == bestOf[0] and z[1] == bestOf[1]:
       # match, compare signals
       if z[7] > bestOf[7]:
           bestOf = z
   else:
        # no match, next set
    f.write(' '.join(bestOf))
    bestOf = z

7 个答案:

答案 0 :(得分:2)

如果未对行进行排序,请使用字典或collections.defaultdict跟踪最大值以跟踪最大值:

from collections import defaultdict

maxima = defaultdict(int)

with open(inputfilename, 'r') as ifh:
    for line in ifh:
        key, value = line.rsplit(None, 1)
        value = int(value)
        if value > maxima[key]:
            maxima[key] = value

with open(outputfilename, 'w') as ofh:
    for key in sorted(maxima):
        ofh.write('{} {}\n'.format(key, maxima[key])

普通字典也可以使用;您可以使用maxima = {}if value > maxima.get(key, 0):代替。

在上面的示例代码中,我使用str.rsplit()来分割分隔两个单词的行中的最后一个空格;这可以确保我们在行尾抓取整数值。该行的其余部分用作键。

如果'key'仅取自该行的 part ,则进一步拆分该行,并存储最大值和行。如果值确实是浮点数,那么到目前为止,您可能希望以float('-inf')作为该键的“最大值”开始:

from collections import defaultdict

maxima = defaultdict(lambda: (float('-inf'), ''))

with open(inputfilename, 'r') as ifh:
    for line in ifh:
        columns = line.rsplit(None, 1)
        key = tuple(columns[:2])    # first two columns are the key
        value = float(columns[-1])  # last column is the value
        if value > maxima[key][0]:
            maxima[key] = (value, line)

with open(outputfilename, 'w') as ofh:
    for key in sorted(maxima):
        # write the tracked lines
        ofh.write(maxima[key][1])

现在,每个键都存储了具有该最大值的最大值。你选择一把钥匙取决于你;我选了前两列。

答案 1 :(得分:1)

您可以使用字典对喜欢进行分组,然后使用max将最后一列的键值转换为浮点数:

data='''\
aaa bbb 10 2.2
aaa bbb 5 3.3
aaa bbb 6 55
aaa bbb 2 6.66
aaa ccc 4 22
aaa ccc 11 35.5
aaa ccc 7 66
aaa ddd 9 .00001
aaa ddd 13 1e10
aaa ddd 12 1e-22
aaa ddd 19 22
xxx yyy 20 123456
xxx yyy 4 66.6666
xxx yyy 6 26
xxx yyy 8 35
xxx yyy 12 2e99
xxx zzz 10 45
xxx zzz 11 55
xxx zzz 4 65
xxx zzz 5 1
xxx zzz 6 12345'''

d={}

for line in data.splitlines():
    l=line.split()
    k=' '.join(l[0:2])      # select how many columns comprise a group
    d.setdefault(k,[]).append(line)

for k in sorted(d):
    max(d[k], key=lambda s: float(s.rsplit(' ',1)[1]))

打印:

aaa bbb 6 55
aaa ccc 7 66
aaa ddd 13 1e10
xxx yyy 12 2e99
xxx zzz 6 12345

答案 2 :(得分:1)

因此,假设您需要最左边的三列是您的标识符,这应该有效:

f = open("test.txt", 'r')
lines = f.readlines()
f.close()

identifiers = set([' '.join(line.split()[0:2]) for line in lines])
output = []

for identifier in identifiers:
    output.append((' '.join(line.split()[:-1], max([float(line.split()[-1]) for line in lines if ' '.join(line.split()[0:2]) == identifier])))

f = open("newFile.txt", 'w')
for item in output:
    f.write("{} {}\n".format(item[0],item[1]))
f.close()

答案 3 :(得分:0)

如果你有很多字段,那么值得使用pandas(这里data是你的样本文本):

>>> import pandas as pd
>>> from StringIO import StringIO
>>> df = pd.read_csv(StringIO(data),sep=' ',header=None)

复制第二列用于测试目的

>>> df[3]=df[2]

按需要的列分组(本例中的前两个)

>>> gb = df.groupby([0,1])

并计算最大值

>>> gb.max().reset_index()
     0    1   2   3
0  aaa  bbb  10  10
1  aaa  ccc  11  11
2  aaa  ddd  19  19
3  xxx  yyy  20  20
4  xxx  zzz  11  11

答案 4 :(得分:0)

以下shell命令是否符合您的要求?

sort -nk3 $filename | tail

这是针对上面的演示数据,并给出:

aaa ccc 11
xxx zzz 11
aaa ddd 12
xxx yyy 12
aaa ddd 13
aaa ddd 19
xxx yyy 20

(用文件名替换$filename,当然......)

对于您提到的8列版本,只需将k3替换为k8,或将您需要的任何列号替换为...

答案 5 :(得分:0)

无需使用任何外部库或任何最大功能。最简单的方法是使用前两个项作为字典的索引,如果在读取数据时大于现有项,则更新该字典中的项。

output_dict = {}
with open(input_file, 'r') as input:
    for row in input:
        id, value = row.rsplit(' ', 1)
        value = int(value)
        if id not in output_dict or value > output_dict[id]:
            output_dict[id] = value


with open(output_file, 'w') as output:
    for id in output_dict:
        output.write('{0} {1}\n'.format(id, output_dict[id]))

将'input_file'和'output_file'替换为文件路径,这将按原样运行,并且应该相对容易理解。对于包含浮点数的数据,可以将'int'替换为'float',它仍然可以工作。

答案 6 :(得分:0)

此解决方案假定要比较的行组合在一起

allLines = r.readlines()
bestOf = re.split(' ', allLines)
f = open("output.txt", 'w')
for line in allLines[2:]:
    z = re.split(' ', line)
    if z[0] == bestOf[0] and z[1] == bestOf[1]:
        # match, compare values
        if z[7] > bestOf[7]:
            bestOf = z
    else:
        # no match, next set
        f.write(bestOf)
        bestOf = z

与选择排序算法类似,如果线条优于当前最佳线条,请改为使用线条。当前两个元素不匹配时,假设我们已经移动到另一个组并将之前的最佳元素写入文件。