将元组列表按相同的元组项拆分为多个列表

11

我被呈现出一个完全由元组组成的列表,例如:

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

我该如何将lst分成与颜色数量相同的多个列表? 在这种情况下,是3个列表。

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

我只需要能够稍后使用这些列表,因此不想将它们仅输出到屏幕上。

关于列表的详细信息

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

问题

问题是,lst依赖于用户输入,因此我不总是知道总共有多少种颜色以及它们是什么。这就是为什么我不能预先定义变量来存储这些列表。那么该怎么做呢?

6个回答

9
您可以使用一个 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')]]

以上方法的优点是,当您添加新键时,它们会自动为空列表进行初始化,因此您无需自己执行此操作。


5
这可以通过使用支持的 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

可以使用dict.values()函数从result中收集列表:

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实现,两者基本相同,不同之处在于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

但是根据您输入的"冲突率",您将获得不同的时序。通常情况下,在低冲突率(即大多数条目会创建dict的新元素)下,split_by_idx()应该是最快的,而在高冲突率下(即大多数条目附加到现有的defaultdict键上),split_by_idx_dd()应该是最快的。


3
在我看来,最好您使用 collections 中的 defaultdict
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
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')]]

我们根据元组的第一个项对列表进行排序,然后再根据元组的第一个项将它们分组。由于“基于第一个项”的重复出现,因此引入了“索引器”变量。

2
你可以用以下方法实现(适用于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')]]

-1
你可以这样做:
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')]]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接