【问题标题】:Outputting items in two combined lists in descending numerical order?按数字降序输出两个组合列表中的项目?
【发布时间】:2015-03-31 17:37:36
【问题描述】:

我有一个如下所示的 txt 文件:

Raj,Joy:9,8,1

史密斯,约翰:8

坎贝尔,米歇尔:5,7,9

注意:文本文件中的文本行之间没有空行

我想按数字降序输出每个人的每个结果,例如

坎贝尔,米歇尔:9

拉吉,乔伊:9

拉吉,乔伊:8

史密斯,约翰:8

坎贝尔,米歇尔:7

等等

我目前的代码是这样的:

            data = src.readlines()
            for line in data:
                record = line.split(':')
                scoreList = record[1].split(',')
                # Add name to fileRecord
                for n in scoreList:
                    fileRecord.append(record[0])

                # Two dimensional list created, each item is one set of scores
                fileScores.append(scoreList)

其中 src 是文本文件。 对我提出的主要问题是,如果我在 sortList 上调用 .sort() 我会丢失顺序,因此无法将每个分数与其对应的名称匹配。如果我要创建一个字典,那么提出的问题是将排序后的数据单独输出为排序

{"Raj,Joy":[9,8,1],etc}

不会按“Raj,Joy”获得的每个单独分数对其进行排序,但我不能拆分列表,因为那样我会有重复的键。

【问题讨论】:

    标签: python arrays file-io text-files


    【解决方案1】:

    Python 单行代码的完美示例。应用列表推导和内置 sorted 函数。

    将组合列表扁平化为元组列表

    scores = [(record, score) for record, scores in zip(fileRecord, fileScores) for score in scores]
    

    按分数降序对元组列表进行排序

    from operator import itemgetter
    sorted(scores, key=itemgetter(1), reverse=True)
    

    问题在一行中解决

    sorted([(record, score) for record, scores in zip(fileRecord, fileScores) for score in scores], key=itemgetter(1), reverse=True)
    

    有用的参考资料

    【讨论】:

      【解决方案2】:
      s = """Raj,Joy:9,8,1
      Smith,John:8
      Campbell,Michelle:5,7,9"""
      

      使用 getKey 提供元组的第二个元素作为 sorted() 的键

      def getKey(item):
          return item[1]
      

      声明你的列表对象

      asc_list = []
      result = []
      

      使用列表推导将输入拆分为单独的行:

      asc_list = [i for i in s.split("\n")]
      asc_list = [(j.split(':')[0],k) for j in asc_list for k in j.split(':')[1].split(',')]
      

      使用 sorted 对元组第 2 项进行排序

      result =  sorted(asc_list_nums, key=getKey)
      

      输出:

      [('Raj,Joy', '1'), ('Campbell,Michelle', '5'), ('Campbell,Michelle', '7'), ('Raj,Joy', '8'), ('Smith,John', '8'), ('Raj,Joy', '9'), ('Campbell,Michelle', '9')]
      

      【讨论】:

        【解决方案3】:

        您可以使用sorted 功能与key 的愿望:

        >>> s="""Raj,Joy:9,8,1
        ... 
        ... Smith,John:8
        ... 
        ... Campbell,Michelle:5,7,9"""
        
        >>> l=s.split('\n\n')
        >>> from itertools import chain    
        >>> for i in sorted(chain(*[[(i[0],j) for j in i[1].split(',')] for i in [i.split(':') for i in l]]),key=lambda x: x[1],reverse=True) :
        ...   print ':'.join(i)
        ... 
        Raj,Joy:9
        Campbell,Michelle:9
        Raj,Joy:8
        Smith,John:8
        Campbell,Michelle:7
        Campbell,Michelle:5
        Raj,Joy:1
        

        所以我们在上面一行代码中的所有内容如下:

        首先我们用两个换行符 ('\n\n') 分割文本并将其放入l

        l=s.split('\n\n') 
        >>> l
        ['Raj,Joy:9,8,1', 'Smith,John:8', 'Campbell,Michelle:5,7,9']
        

        那么您需要创建一个包含名称和分数的对列表:

        >>> [[(i[0],j) for j in i[1].split(',')] for i in [i.split(':') for i in l]]
        [[('Raj,Joy', '9'), ('Raj,Joy', '8'), ('Raj,Joy', '1')], [('Smith,John', '8')], [('Campbell,Michelle', '5'), ('Campbell,Michelle', '7'), ('Campbell,Michelle', '9')]]
        

        最后,您需要首先链接嵌套列表,然后使用 sorted 函数和以下键根据第二个元素(分数)对该列表进行排序:

        key=lambda x: x[1]
        

        如果你想写入文件:

        with open ('sample_file','w') as f :
             for i in sorted(chain(*[[(i[0],j) for j in i[1].split(',')] for i in [i.split(':') for i in l]]),key=lambda x: x[1],reverse=True) :
                f.write(':'.join(i))
        

        【讨论】:

        • 这与 OPs 输出不匹配 - 每个分数出现的名称应输出多次
        • @KasraAD 或许我们可以创建多个字典来避免重复键,但是效率非常低且过于复杂,尤其是在排序时。
        • @KasraAD 你能解释一下你的编辑吗,因为我不明白
        • @joyalrj22 是的,请稍等!
        • @KasraAD 是否可以将 .split() 方法替换为 record = line.split(':'), scoreList = record[1].split(',')
        【解决方案4】:

        您已经填写了fileRecordfileScores。现在你将它们组合起来并排序:

        >>> fileRecord = ['Raj,Joy', 'Smith,John', 'Campbell,Michelle']
        
        >>> fileScores = [[9, 8, 1], [8], [5, 7, 9]]
        
        >>> comb = []
        
        >>> for record, scores in zip(fileRecord, fileScores):
        ...     for score in scores:
        ...         comb.append((record, score))
        ...         
        
        >>> comb
        >>> 
        [('Raj,Joy', 9),
         ('Raj,Joy', 8),
         ('Raj,Joy', 1),
         ('Smith,John', 8),
         ('Campbell,Michelle', 5),
         ('Campbell,Michelle', 7),
         ('Campbell,Michelle', 9)]
        
        >>> comb.sort(key=lambda item: item[1], reverse=True)
        
        >>> comb
        >>> 
        [('Raj,Joy', 9),
         ('Campbell,Michelle', 9),
         ('Raj,Joy', 8),
         ('Smith,John', 8),
         ('Campbell,Michelle', 7),
         ('Campbell,Michelle', 5),
         ('Raj,Joy', 1)]
        

        您可能希望使用itertools.izip 而不是 Python 2 中内置的 zip

        【讨论】:

          【解决方案5】:

          打开文件并str.rpartition 每行以将数字与名称隔离开来。然后构建一个生成器,用它的每个数字扩展名称,对其进行排序,然后做任何你需要的输出,例如:

          代码:

          with open('input_file') as fin:
              name_nums = (line.rpartition(':')[::2] for line in fin)
              expanded = ((name, int(n)) for name, num in name_nums for n in num.split(','))
              ordered = sorted(expanded, key=lambda L: L[1], reverse=True)
              for name, num in ordered:
                  print '{}:{}'.format(name, num)
          

          输出

          Raj,Joy:9
          Campbell,Michelle:9
          Raj,Joy:8
          Smith,John:8
          Campbell,Michelle:7
          Campbell,Michelle:5
          Raj,Joy:1
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-12-11
            • 2021-04-02
            • 1970-01-01
            • 2015-05-15
            • 2023-01-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多