解压混合元组列表

时间:2018-07-12 05:14:31

标签: python dictionary tuples

我有一个混合元组列表:

my_list = [("Adam",1985),("Karen",1990),("anna",1986)] 

如何将其分别包装成两个列表或元组,一个包含字符串,一个包含整数?

3 个答案:

答案 0 :(得分:2)

如果列表架构保持为(str, int)

使用python的zip,您可以轻松拆开元组列表,而无需特别注意类型:

my_list = [("Adam",1985),("Karen",1990),("anna",1986)] 
names, years = zip(*my_list)

未包装的清单是:

('Adam', 'Karen', 'anna'), (1985, 1990, 1986)

关于*运算符的注意事项

*运算符称为Unpacking Argument Lists,它将列表的单个元素作为参数传递。假设您有一个包含3个元素的列表my_list = [1, 2, 3]和一个具有3个参数def func(a, b, c)的函数:您可以使用func(*my_list)来调用func(my_list[0], my_list[1], ..., my_list[n])

如果列表架构被改组

使用排序的解决方案,一个元组一个元组

使用functools.cmp_to_key,我们可以先对元组进行排序,然后执行zip:

import functools
key=functools.cmp_to_key(lambda x1, x2: 1 if isinstance(x2, str) else -1)
names, years = zip(*[sorted(t, key=key) for t in l])

这样,列表首先被排序为:

[['Adam', 1985], ['Karen', 1990], ['anna', 1986]]

然后运行zip文件,我们将获得相同的结果:

('Adam', 'Karen', 'anna'), (1985, 1990, 1986)

使用groupby解决方案

from itertools import chain, groupby
names, years = [
    list(v) for _, v in groupby(
        sorted(chain.from_iterable(my_list), key=lambda x: str(x)),
        lambda x: isinstance(x, str))
]

示例列表中的解决方案速度比较

在示例列表上的运行时间,我们得到:

元组排序:

%timeit zip(*[sorted(t, key=key) for t in my_list])
>>> 5.2 µs ± 157 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

分组依据

%timeit [list(v) for _, v in groupby(sorted(chain.from_iterable(my_list), key=lambda x: str(x)), lambda x: isinstance(x, str))]
>>> 6.83 µs ± 358 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

大列表解决方案速度比较

大型列表上的运行时间,例如:

import random
n = 100000
my_list = []
for i in range(n):
    if random.choice([True, False]):
        my_list.append((i, "Karen"))
    else:
        my_list.append(("Karen", i))

元组排序:

%timeit zip(*[sorted(t, key=key) for t in my_list])
>>> 166 ms ± 8.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

分组依据

%timeit [list(v) for _, v in groupby(sorted(chain.from_iterable(my_list), key=lambda x: str(x)), lambda x: isinstance(x, str))]
>>> 149 ms ± 2.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

结论

即使在较小的列表中,第一种方法似乎速度更快,在较大的列表中,groupby方法显得更快。

答案 1 :(得分:2)

使用zip

>>> years, names = zip(*(sorted(t, key=lambda x: str(type(x))) for t in my_list))
>>> years
(1985, 1990, 1986)
>>> names
('Adam', 'Karen', 'anna')
>>> 

或使用dict

>>> d = dict(sorted(t, key=lambda x: str(type(x))) for t in my_list)
>>> years = tuple(d.keys())
>>> names = tuple(d.values())
>>> 
>>> years
(1985, 1990, 1986)
>>> names
('Adam', 'Karen', 'anna')
>>> 

答案 2 :(得分:1)

您可以将其转换为字典并正常使用

dict([("Adam",1985),("Karen",1990),("anna",1986)])
  

{'亚当':1985年,'卡伦':1990年,'安娜':1986年}