Python 3.4.3 - 按字母顺序对统计列表进行排序
Python 3.4.3 - Sorting statistical list alphabetically
我有一个文本文件,其中显示了示例名称列表,后面是他们在算术测试中获得的分数。
Aaa = 10
Ccc = 9
Ddd = 1
Bbb = 5
在另一个脚本中,我需要能够 select 一个选项来按字母顺序对列表进行排序,并在将更多名称添加到列表中后维持这一点,如下所示:
Aaa = 10
Bbb = 5
Ccc = 9
Ddd = 1
这样,名字就会按字母顺序列出,并与它们的原始分数相邻。我试过 sort
函数,
f=open('score.txt','r')
readfile=str(f.readlines())
readfile.rstrip('\n')
print(sorted(readfile))
但是这只会对文件的每个字符进行排序,returns 这个:
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', "'", "'", "'", "'", "'", "'", "'", "'", ',', ',', ',', '0', '1', '1', '5', '9', '=', '=', '=', '=', 'A', 'B', 'C', 'D', '[', '\', '\', '\', '\', ']', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 'n', 'n', 'n', 'n']
您正在使用 str(f.readlines())
创建从 readlines 返回的列表的字符串表示形式,因此调用 sorted 将对每个字符进行排序,只需调用 sorted 文件对象:
with open("in.txt") as f:
print(sorted(f))
输出:
['Aaa = 10\n', 'Bbb = 5', 'Ccc = 9\n', 'Ddd = 1\n']
要删除换行符,请使用地图:
with open("in.txt") as f:
lines = map(str.rstrip,sorted(f))
print(lines)
输出:
['Aaa = 10', 'Bbb = 5', 'Ccc = 9', 'Ddd = 1']
基本上你的代码中发生了什么:
In [4]: l = ["1","2","3","4"] # readlines list
In [5]: str(l) # you turn it into a str
Out[5]: '[1, 2, 3, 4]'
In [6]: sorted(str(l)) # calling sorted sorts the individual characters
Out[6]: [' ', ' ', ' ', ',', ',', ',', '1', '2', '3', '4', '[', ']']
一旦你有一个排序的文件,为了将新名称放在正确的位置,你可以使用一个临时文件写入并替换原始文件 shutil.move:
new_n, new_s = "Bar",12
from shutil import move
from tempfile import NamedTemporaryFile
with open("in.txt") as f, NamedTemporaryFile("w",dir=".",delete=False) as t:
for line in f:
if line >= new_n:
t.write("{} = {}\n".format(new_n, new_s))
t.write(line)
t.writelines(f)
break
t.write(line)
else:
t.write("{} = {}\n".format(new_n, new_s))
move(t.name,"in.txt")
原来排序后写in.txt:
Aaa = 10
Bbb = 5
Ccc = 9
Ddd = 1
in.txt 在 运行 代码之后:
Aaa = 10
Bar = 12
Bbb = 5
Ccc = 9
Ddd = 1
如果下一个运行我们加上"Foo":
Aaa = 10
Bar = 12
Bbb = 5
Ccc = 9
Ddd = 1
Foo = 12
else 被执行,因为我们没有发现 line/name 大于或等于 foo。
如果你有一个排序列表,并且你想将新数据插入列表并保持顺序,你可以使用 bisect 模块:
new_n, new_s = "Bar",12
from bisect import insort
with open("in.txt") as f:
lines = sorted(f)
insort(lines,"{} = {}".format(new_n, new_s))
print(lines)
输出:
['Aaa = 10\n', 'Bar = 12\n', 'Bbb = 5\n', 'Ccc = 9\n', 'Ddd = 1\n']
你没有列表,你有 一个字符串:
readfile=str(f.readlines())
这会将您的列表转换为字符串,包括 [
、]
开头和结尾以及原始行之间的 ,
逗号。
不要那样做,这里完全没有必要将字符串列表转换为字符串。只需对您阅读的行进行排序:
readfile = f.readlines()
print(sorted(readfile))
你甚至不需要在这里调用 f.readlines()
,因为 sorted()
可以接受任何可迭代对象,包括文件对象:
with open('score.txt') as infile:
readfile = sorted(infile)
print(readfile)
您需要注意,如果文件中有任何重复的名称,它们将根据 =
字符后的数字而不是数字按字典顺序排序。这意味着 100
排在 9
之前,因为 1
在 Unicode 标准中排在 9
之前。
我有一个文本文件,其中显示了示例名称列表,后面是他们在算术测试中获得的分数。
Aaa = 10
Ccc = 9
Ddd = 1
Bbb = 5
在另一个脚本中,我需要能够 select 一个选项来按字母顺序对列表进行排序,并在将更多名称添加到列表中后维持这一点,如下所示:
Aaa = 10
Bbb = 5
Ccc = 9
Ddd = 1
这样,名字就会按字母顺序列出,并与它们的原始分数相邻。我试过 sort
函数,
f=open('score.txt','r')
readfile=str(f.readlines())
readfile.rstrip('\n')
print(sorted(readfile))
但是这只会对文件的每个字符进行排序,returns 这个:
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', "'", "'", "'", "'", "'", "'", "'", "'", ',', ',', ',', '0', '1', '1', '5', '9', '=', '=', '=', '=', 'A', 'B', 'C', 'D', '[', '\', '\', '\', '\', ']', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 'n', 'n', 'n', 'n']
您正在使用 str(f.readlines())
创建从 readlines 返回的列表的字符串表示形式,因此调用 sorted 将对每个字符进行排序,只需调用 sorted 文件对象:
with open("in.txt") as f:
print(sorted(f))
输出:
['Aaa = 10\n', 'Bbb = 5', 'Ccc = 9\n', 'Ddd = 1\n']
要删除换行符,请使用地图:
with open("in.txt") as f:
lines = map(str.rstrip,sorted(f))
print(lines)
输出:
['Aaa = 10', 'Bbb = 5', 'Ccc = 9', 'Ddd = 1']
基本上你的代码中发生了什么:
In [4]: l = ["1","2","3","4"] # readlines list
In [5]: str(l) # you turn it into a str
Out[5]: '[1, 2, 3, 4]'
In [6]: sorted(str(l)) # calling sorted sorts the individual characters
Out[6]: [' ', ' ', ' ', ',', ',', ',', '1', '2', '3', '4', '[', ']']
一旦你有一个排序的文件,为了将新名称放在正确的位置,你可以使用一个临时文件写入并替换原始文件 shutil.move:
new_n, new_s = "Bar",12
from shutil import move
from tempfile import NamedTemporaryFile
with open("in.txt") as f, NamedTemporaryFile("w",dir=".",delete=False) as t:
for line in f:
if line >= new_n:
t.write("{} = {}\n".format(new_n, new_s))
t.write(line)
t.writelines(f)
break
t.write(line)
else:
t.write("{} = {}\n".format(new_n, new_s))
move(t.name,"in.txt")
原来排序后写in.txt:
Aaa = 10
Bbb = 5
Ccc = 9
Ddd = 1
in.txt 在 运行 代码之后:
Aaa = 10
Bar = 12
Bbb = 5
Ccc = 9
Ddd = 1
如果下一个运行我们加上"Foo":
Aaa = 10
Bar = 12
Bbb = 5
Ccc = 9
Ddd = 1
Foo = 12
else 被执行,因为我们没有发现 line/name 大于或等于 foo。
如果你有一个排序列表,并且你想将新数据插入列表并保持顺序,你可以使用 bisect 模块:
new_n, new_s = "Bar",12
from bisect import insort
with open("in.txt") as f:
lines = sorted(f)
insort(lines,"{} = {}".format(new_n, new_s))
print(lines)
输出:
['Aaa = 10\n', 'Bar = 12\n', 'Bbb = 5\n', 'Ccc = 9\n', 'Ddd = 1\n']
你没有列表,你有 一个字符串:
readfile=str(f.readlines())
这会将您的列表转换为字符串,包括 [
、]
开头和结尾以及原始行之间的 ,
逗号。
不要那样做,这里完全没有必要将字符串列表转换为字符串。只需对您阅读的行进行排序:
readfile = f.readlines()
print(sorted(readfile))
你甚至不需要在这里调用 f.readlines()
,因为 sorted()
可以接受任何可迭代对象,包括文件对象:
with open('score.txt') as infile:
readfile = sorted(infile)
print(readfile)
您需要注意,如果文件中有任何重复的名称,它们将根据 =
字符后的数字而不是数字按字典顺序排序。这意味着 100
排在 9
之前,因为 1
在 Unicode 标准中排在 9
之前。