Python从文本文件降序

时间:2014-12-18 16:03:03

标签: python-3.x

目前我按照这样的降序对文本文件进行排序:

import operator
fo = open('3a.txt','r')
x = fo.readlines()
sorted_x = sorted(x, key=operator.itemgetter(0),reverse = True)
print(sorted_x)

我的文本文件如下所示:

5 Helen 
4 judy
8 Rachel

我想知道如何将operator.itemgetter(0)用于双数字?

当我使用它时:

5 Helen 
4 judy
25 Hanna
11 Elsa
8 Rachel

结果都错了:

['8 Rachel', '5 Helen', '4 judy', '25 Hanna', '11 Elsa']

即使我使用operator.itemgetter(0, 1)

1 个答案:

答案 0 :(得分:11)

你的operator.itemgetter(0)方法只能让你到目前为止;它总是会选择你的行的第一个字符。

要以数字方式对文件进行正确排序,您的key函数必须执行以下操作:

  1. 正确地将该行开头的数字与其余部分分开。
  2. 将表示数字的字符串转换为正确的整数值。
  3. 后者很重要,因为排序字符串是按字典顺序完成的;例如'10''9'之前排序,因为1位于9之前。

    要在行的开头支持任意数字字符运行(由空格分隔),您需要拆分空白str.split() method可以为您执行此操作,如果您不给它任何参数或使用None作为第一个参数。为了保持高效,将分割数限制为1,并将结果的第一个元素转换为整数:

    fo = open('3a.txt','r')
    x = fo.readlines()
    sort_key = lambda line: int(line.split(None, 1)[0])
    sorted_x = sorted(x, key=sort_key, reverse=True)
    print(sorted_x)
    

    因此key参数被赋予一个匿名函数(lambda),该函数接受一个参数,该行被排序。该行仅在空格上拆分一次(line.split(None, 1),并且该拆分的第一个元素变为整数:

    >>> '11 Hello World'.split(None, 1)
    ['11', 'Hello World']
    >>> '11 Hello World'.split(None, 1)[0]
    '11'
    >>> int('11 Hello World'.split(None, 1)[0])
    11
    

    您也可以改进其余的实施;由于文件是可迭代的,因此无需调用file.readlines()sorted()将把所有内容都放在一个可迭代的中并对其进行排序,这样你就可以将整个文件对象直接传递给函数。

    您还希望处理文件,以便在完成后自动关闭它们。利用他们是上下文管理者的事实;当上下文“完成”(已结束)并且文件对象将自动关闭时,with语句将向它们发出信号:

    sort_key = lambda line: int(line.split(None, 1)[0])
    
    with open('3a.txt','r') as fo:
        sorted_x = sorted(fo, key=sort_key, reverse=True)
    
    print(sorted_x)
    

    演示:

    >>> from io import StringIO
    >>> fo = StringIO('''\
    ... 5 Helen 
    ... 4 judy
    ... 25 Hanna
    ... 11 Elsa
    ... 8 Rachel
    ... '''
    ... )
    >>> sort_key = lambda line: int(line.split(None, 1)[0])
    >>> sorted(fo, key=sort_key, reverse=True)
    ['25 Hanna\n', '11 Elsa\n', '8 Rachel\n', '5 Helen \n', '4 judy\n']
    

    只有当您首先将行拆分为列表时,您才能完成此操作且仍然使用operator.itemgetter(0) ,其中元素0是整数:

    import operator
    
    sort_key = operator.itemgetter(0)
    
    with open('3a.txt','r') as fo:
        split_lines = (line.split(None, 1) for line in fo)
        numeric_lines = ((int(line[0]), line[1]) for line in split_lines)
        sorted_x = sorted(numeric_lines, key=sort_key, reverse=True)
    
    print(sorted_x)
    

    这使用生成器表达式来处理正在读取的行。但是现在你有一个列表,每个元素都有一个元组,一个整数和你的其余部分:

    >>> import operator
    >>> fo = StringIO('''\
    ... 5 Helen 
    ... 4 judy
    ... 25 Hanna
    ... 11 Elsa
    ... 8 Rachel
    ... ''')
    >>> sort_key = operator.itemgetter(0)
    >>> split_lines = (line.split(None, 1) for line in fo)
    >>> numeric_lines = ((int(line[0]), line[1]) for line in split_lines)
    >>> sorted(numeric_lines, key=sort_key, reverse=True)
    [(25, 'Hanna\n'), (11, 'Elsa\n'), (8, 'Rachel\n'), (5, 'Helen \n'), (4, 'judy\n')]