繁体   English   中英

通过python中的第一个元素重新组合子列表

[英]Regroup sublists by first element in python

我有一个嵌套列表,看起来像这样:

first_list = [[a, 1], [b, 3], [a, 6], [a, 2], [b, 4], [b, 5], ...]

我想按它们的第一个元素对它们进行分组,并创建一个新的嵌套列表,如下所示:

new_list = [ [1, 6, 2, ...], [3, 4, 5, ...], ...]

所有以go开头的元素都位于第一个子列表中,依此类推。 在运行时之前不知道不同值a,b等的数量,或者我可以执行以下操作:

a_list = []
b_list = []
for tag, x in first_list:
    if tag == a:
        a_list.append(x)
    elif tag == b:
        b_list.append(x)
new_list = [a_list, b_list]

但是,我正在努力使它适应任意数量的标签。

我可能省略了问题的重要部分,但我应该说我已经有一个“标签”列表,即:

tags = [a, b, c, d, ...]

它们实际上不是字符,因此没有反逗号,但是无论如何它们都应该是可哈希的。

首先,您的a和b可能应该是字符串。

您可以使用列表推导来做到这一点:

first_list = [["a", 1], ["b", 3], ["a", 6], ["a", 2], ["b", 4], ["b", 5]]
a_list = [x for x in first_list if x[0] == "a"]
b_list = [x for x in first_list if x[0] == "b"]
new_list = [a_list, b_list]

使用Python和一般的编程,应该避免创建数量可变的变量。

defaultdict

您可以使用list对象的defaultdict 这自然可以扩展到任意数量的组,而不必显式命名变量。

first_list = [['a', 1], ['b', 3], ['a', 6], ['a', 2], ['b', 4], ['b', 5]]

from collections import defaultdict

dd = defaultdict(list)

for cat, num in first_list:
    dd[cat].append(num)

defaultdict(list, {'a': [1, 6, 2],
                   'b': [3, 4, 5]})

通过...分组

defaultdict解决方案具有O( n )复杂度,但是可以适当地命名为itertools.groupby解决方案,这需要排序和O( n log n )复杂度:

from itertools import groupby
from operator import itemgetter

sorter = sorted(first_list, key=itemgetter(0))
grouper = groupby(sorter, key=itemgetter(0))
res = {i: list(map(itemgetter(1), j)) for i, j in grouper}

{'a': [1, 6, 2], 'b': [3, 4, 5]}

清单输出清单

这是因为调用微不足道listdict.values

res_list = list(res.values())

这是使用itertools库和列表理解的绝佳机会:

first_list = [['a', 1], ['b', 3], ['a', 6], ['a', 2], ['b', 4], ['b', 5], ...]
keyfunc = lambda x: x[0]
new_list = [[v1[1] for v1 in v] for k, v in itertools.groupby(sorted(first_list, key = keyfunc), key = keyfunc)]

我在这里所做的是按子列表中的第一个值对列表进行分组,然后提取第二个值。 请注意,列表需要事先排序,因此它将在O(n log n)时间内运行。

减少将适用于任何数量的标签。

first_list = [['a', 1], ['b', 3], ['a', 6], ['a', 2], ['b', 4], ['b', 5]]
def lambda_group(acc, val):
    tag, x = val
    if key not in acc:
        acc[key] = []
    acc[key].append(value)
    return acc
grouped_vals = reduce(lambda_group, first_list, {})
regrouped = list(grouped_vals.values())

产生[[1, 6, 2], [3, 4, 5]] 1,6,2 [[1, 6, 2], [3, 4, 5]]

好的,在python中有一个内置方法,但是以抽象算法的方式,我们可以说:

first_list = [["a", 1], ["b", 3], ["a", 6], ["a", 2], ["b", 4], ["b", 5],["c",5]]

indx_list = [x[0] for x in first_list]

new_list = [[] for x in range(len(first_list))]

for x in first_list:
    new_list[indx_list.index(x[0])] += [x[-1]]

print(new_list)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM