使用 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)
我有一个未按数字排序的数据文件(轨迹文件)。数据文件由文本和数字重复组成,如下所示。如您所见,前 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)