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

TGa*_*mer 10 python split tuples list

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

lst = [("hello", "Blue"), ("hi", "Red"), ("hey", "Blue"), ("yo", "Green")]
Run Code Online (Sandbox Code Playgroud)

我怎样才能lst分成与颜色一样多的列表?在这种情况下,3个列表

[("hello", "Blue"), ("hey", "Blue")]
[("hi", "Red")]
[("yo", "Green")]
Run Code Online (Sandbox Code Playgroud)

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

名单详情

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

问题

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

那么如何做到这一点呢?

Roa*_*ner 8

您可以使用 acollections.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')]})
Run Code Online (Sandbox Code Playgroud)

或者,如果您更喜欢不使用库,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')]}
Run Code Online (Sandbox Code Playgroud)

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

print(list(colours.values()))
# [[('hello', 'Blue'), ('hey', 'Blue')], [('hi', 'Red')], [('yo', 'Green')]]
Run Code Online (Sandbox Code Playgroud)

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


nor*_*ok2 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
Run Code Online (Sandbox Code Playgroud)

和列表可以从收集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')]]
Run Code Online (Sandbox Code Playgroud)

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

def split_by_idx_sd(items, idx=1):
    result = {}
    for item in items:
        result.setdefault(item[idx], []).append(item)
    return result
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)

时间上,dict基于-based的解决方案对于您的输入是最快的:

%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
Run Code Online (Sandbox Code Playgroud)

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