使用 python 对文件进行排序

Sorting a file with python

我有一个未按数字排序的数据文件(轨迹文件)。数据文件由文本和数字重复组成,如下所示。如您所见,前 4 行只是信息,排序的实数从第五行开始。再一次,另外四行只是信息,然后数字从第五行开始。那些重复了一百个块。我想将它们按数字排序为第一列。

ITEM: TIMESTEP
0
ITEM: NUMBER OF ATOMS
ITEM: ATOMES id type x y z
4959 8 10.1 20.1 41.1
5029 8 13.1 43.1 5.3
....
ITEM: TIMESTEP
100
ITEM: NUMBER OF ATOMS
ITEM: ATOMES id type x y z
1259 8 10.1 20.1 41.1
6169 8 13.1 43.1 5.3
....
ITEM: TIMESTEP
200
ITEM: NUMBER OF ATOMS
ITEM: ATOMES id type x y z
3523 8 10.1 20.1 41.1
9119 8 13.1 43.1 5.3
....

我试图制作一个 python 脚本。我的想法是将'ITEM: ATOMES id type x y z'和ITEM: NUMBER of ATOMS之间的每个数字块放入列表中,然后在列表中对它们进行排序并打印它们。我已将它们放入列表中,但每个元素(例如 4959 8 10.1 20.1 41.1)只是一个字符串。如何排序为列表中字符串的第一列?

我试过如下。你能给我一些建议吗?

f_in=open('aa', 'r')

def SORT(List):

        print 'ITEM: TIMESTEP'
        print 'Num of Trajectory'
        print 'ITEM: NUMBER OF ATOMS'
        print 'ATOMS'
        print 'ITEM: BOX BOUNDS pp pp pp'
        print '\n\n'
        print 'ITEM: ATOMS id type x y z'

        for p in List:
                print p

LIST=[]

a = 1

for line in f_in:

        sp = line.split()

        if(len(sp) != 5):
                continue
        else:
                if(a < 5085):
                        LIST.append(line)
                        a = a + 1
                elif(a == 5085):
                        LIST.append(line)
                        LIST = map(lambda s: s.strip(), LIST)
                        SORT(LIST)
                        a = 1

获得列表后,您可以使用排序的关键参数进行排序。

numberList.sort(key=lambda line: int(line.split()[0]))

这告诉排序使用转换为整数的行中的第一项作为排序键。

但是,如果以文本开头的任何行都在列表中,这将不起作用。转换为 int 将失败。你必须先过滤掉那些。

以下脚本将读入您的文件并对每个块中的行进行排序:

from itertools import groupby

with open('input.txt') as f_input, open('output.txt', 'w') as f_output:
    for k, g in groupby(f_input, lambda x: x != 'ITEM: TIMESTEP\n'):
        if k:
            entries = [line.strip() for line in g]
            block_header = ['ITEM: TIMESTEP'] + entries[:3]
            entries = sorted([line.split() for line in entries[3:]], key=lambda x: int(x[0]))
            f_output.write('\n'.join(block_header) + '\n')

            for row in entries:
                f_output.write(' '.join(row) + '\n')

利用Python的groupby函数,在ITEM: TIMESTEP的基础上分块读入文件。然后它从每一行中去除新行,并仅提取具有值的行。然后,它根据空格拆分这些行中的每一行,并通过将第一个条目转换为整数来对这些行进行排序。

然后将这些行中的每一行写入输出文件,为每个相同的块提供 header。

您也可以试试:

import re
f_in=open('aa', 'r')

def SORT(List):

        print 'ITEM: TIMESTEP'
        print 'Num of Trajectory'
        print 'ITEM: NUMBER OF ATOMS'
        print 'ATOMS'
        print 'ITEM: BOX BOUNDS pp pp pp'
        print '\n\n'
        print 'ITEM: ATOMS id type x y z'

        for p in List:
                print p

result = [] # real numbers list

# read whole content into a list
lines= f_in.readlines()
# enumerate each line and find only the numers
# append each found item into result list
for line in lines:
    m = re.findall('^[0-9\s\.].+', line.strip('\n'))
    if m: result.append(m[0])
    else: continue
# split result list into chunks (5085)
for i in xrange(0, len(result), 5085):
    LIST = result[i:i+5085]
    SORT(LIST)