【问题标题】:Splitting a list of tuples to several lists by the same tuple items [duplicate]通过相同的元组项将元组列表拆分为多个列表[重复]
【发布时间】:2020-08-24 21:57:41
【问题描述】:

我看到了一个完全由元组组成的列表,例如:

lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]

如何将lst 拆分为与颜色一样多的列表?在这种情况下,3 个列表

[("hello", "Blue"), ("hey", "Blue")]
[("hi", "Red")]
[("yo", "Green")]

我只需要以后能够使用这些列表,所以我不想只是将它们输出到屏幕上。

列表详情

我知道lst 的每个元素严格来说都是一个双元素元组。颜色也始终是每个元组的第二个元素。

问题

问题是,lst 取决于用户输入,所以我并不总是知道总共有多少种颜色以及它们是什么。这就是为什么我无法预定义变量以将这些列表存储在其中。

那么如何做到这一点呢?

【问题讨论】:

    标签: python list split tuples


    【解决方案1】:

    这可以通过支持dict 相对有效地完成:

    def split_by_idx(items, idx=1):
        result = {}
        for item in items:
            key = item[idx]
            if key not in result:
                result[key] = []
            result[key].append(item)
        return result
    

    并且可以从resultdict.values() 收集列表:

    lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]
    
    
    d = split_by_idx(lst)
    print(list(d.values()))
    # [[('hello', 'Blue'), ('hey', 'Blue')], [('hi', 'Red')], [('yo', 'Green')]]
    

    这也可以使用dict.setdefault()defaultdict 来实现,除了您不必明确处理“密钥不存在”的情况外,它们基本相同:

    def split_by_idx_sd(items, idx=1):
        result = {}
        for item in items:
            result.setdefault(item[idx], []).append(item)
        return result
    
    import collections
    
    
    def split_by_idx_dd(items, idx=1):
        result = collections.defaultdict(list)
        for item in items:
            result[item[idx]].append(item)
        return result
    

    在时间上,基于dict 的解决方案是您输入速度最快的:

    %timeit split_by_idx(lst)
    # 1000000 loops, best of 3: 776 ns per loop
    %timeit split_by_idx_sd(lst)
    # 1000000 loops, best of 3: 866 ns per loop
    %timeit split_by_idx_dd(lst)
    # 1000000 loops, best of 3: 1.16 µs per loop
    

    但是根据输入的“冲突率”,您会得到不同的时间。一般而言,您应该期望split_by_idx() 在低碰撞率下最快(即大多数条目创建dict 的新元素),而split_by_idx_dd() 在高碰撞率下应该是最快的(即大多数条目会附加到现有的 defaultdict 键)。

    【讨论】:

      【解决方案2】:

      在我看来,你最好使用来自collectionsdefaultdict

      from collections import defaultdict
      colors = defaultdict(list)
      for word, color in lst:
          colors[color].append(word)
      

      这将为您提供更好的数据结构

      >>> colors
      defaultdict(list, {'Blue': ['hello', 'hey'], 'Green': ['yo'], 'Red': ['hi']})
      

      例如,您可以这样处理:

      >>> for key, values in colors.items():
      ...     print([[key, value] for value in values])
      ...     
      [['Blue', 'hello'], ['Blue', 'hey']]
      [['Red', 'hi']]
      [['Green', 'yo']]
      

      【讨论】:

        【解决方案3】:

        你可以这样做(python 3):

        lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]
        colors = {elem[1] for elem in lst}  # make set of colors
        colors = dict.fromkeys(colors, [])  # turn the set of colors into dict
        
        for t in lst:
            colors[t[1]] = [*colors[t[1]], t]
        

        如果你只想要颜色元组,你可以打印颜色字典的 values():

        print(list(colors.values()))
        # [[('hello', 'Blue'), ('hey', 'Blue')], [('hi', 'Red')], [('yo', 'Green')]]
        

        【讨论】:

          【解决方案4】:
          from itertools import groupby
          from operator import itemgetter
          
          indexer = itemgetter(1)
          desired = [list(gr) for _, gr in groupby(sorted(lst, key=indexer), key=indexer)]
          # [[('hello', 'Blue'), ('hey', 'Blue')], [('yo', 'Green')], [('hi', 'Red')]]
          

          我们根据元组的第一项对列表进行排序,然后根据元组的第一项对它们进行分组。重复“基于第一项”,因此有 indexer 变量。

          【讨论】:

            【解决方案5】:

            您可以使用collections.defaultdict 按颜色分组:

            from collections import defaultdict
            
            lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]
            
            colours = defaultdict(list)
            for word, colour in lst:
                colours[colour].append((word, colour))
            
            print(colours)
            # defaultdict(<class 'list'>, {'Blue': [('hello', 'Blue'), ('hey', 'Blue')], 'Red': [('hi', 'Red')], 'Green': [('yo', 'Green')]})
            

            或者,如果您不喜欢使用任何库,dict.setdefault 是一个选项:

            colours = {}
            for word, colour in lst:
                  colours.setdefault(colour, []).append((word, colour))
            
            print(colours)
            # {'Blue': [('hello', 'Blue'), ('hey', 'Blue')], 'Red': [('hi', 'Red')], 'Green': [('yo', 'Green')]}
            

            如果您只想将颜色元组分成嵌套的元组列表,请将values() 打印为列表:

            print(list(colours.values()))
            # [[('hello', 'Blue'), ('hey', 'Blue')], [('hi', 'Red')], [('yo', 'Green')]]
            

            上述方法的好处是它们会在您添加新键时自动为新键初始化空列表,因此您不必自己这样做。

            【讨论】:

              【解决方案6】:

              你可以这样做:

              lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]
              colors = {elem[1] for elem in lst}
              
              lsts = []
              
              for color in colors:
                  color_lst = [elem for elem in lst if elem[1] == color]
                  lsts.append(color_lst)
              

              colors 包含 lst 中存在的唯一颜色(集合理解确保了这种唯一性),lsts 将包含您需要的最后 3 个列表。

              lsts 的最终结果如下:[[('hi', 'Red')], [('yo', 'Green')], [('hello', 'Blue'), ('hey', 'Blue')]]

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2019-10-20
                • 1970-01-01
                • 1970-01-01
                • 2014-04-27
                • 2017-07-30
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多