Python 3.4.3 - 按字母顺序排序统计列表

时间:2015-08-28 12:57:25

标签: python sorting python-3.4

我有一个文本文件,显示示例名称列表,然后他们的分数获得了算术测试。

Aaa = 10
Ccc = 9
Ddd = 1
Bbb = 5

在另一个脚本中,我需要能够选择一个选项来按字母顺序对列表进行排序,并在将更多名称添加到列表后维持这一点,如下所示:

Aaa = 10
Bbb = 5
Ccc = 9
Ddd = 1

这样,名称按字母顺序列出,并与其原始分数相邻。我试过了sort函数,

 f=open('score.txt','r')
 readfile=str(f.readlines())
 readfile.rstrip('\n')
 print(sorted(readfile))

但是,这只对文件的每个字符进行排序并返回:

[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', "'", "'", "'", "'", "'", "'", "'", "'", ',', ',', ',', '0', '1', '1', '5', '9', '=', '=', '=', '=', 'A', 'B', 'C', 'D', '[', '\\', '\\', '\\', '\\', ']', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd', 'n', 'n', 'n', 'n']

2 个答案:

答案 0 :(得分:2)

您正在使用str(f.readlines())创建从readlines返回的列表的字符串表示形式,因此对其进行排序将对每个字符进行排序,只需在文件对象上调用sort:

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,因为我们发现没有大于或等于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']

答案 1 :(得分:0)

您没有列表,您有一个字符串

readfile=str(f.readlines())

这会将您的列表转换为字符串,包括[]开头和结尾以及原始行之间的,逗号。

不要这样做,绝对不需要将字符串列表转换为字符串。只需对您阅读的行进行排序:

readfile = f.readlines()
print(sorted(readfile))

您甚至不需要在此处调用f.readlines(),因为sorted()可以使用任何可迭代的内容,包括文件对象:

with open('score.txt') as infile:
    readfile = sorted(infile)

print(readfile)

您需要考虑到,如果文件中有任何重复的名称,它们将按照=字符后面的数字按字典顺序排序,而不是数字。这意味着1009之前排序,因为1在Unicode标准中位于9之前。