按 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" 的列表,即:
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
个对象。这自然地扩展到任意数量的组,而无需显式命名变量。
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]}
列表输出列表
这就像在 dict.values
上调用 list
一样微不足道:
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)
时间内 运行。
reduce 适用于任意数量的标签。
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]]
好的,在 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)
我有一个看起来像这样的嵌套列表:
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" 的列表,即:
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
个对象。这自然地扩展到任意数量的组,而无需显式命名变量。
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]}
列表输出列表
这就像在 dict.values
上调用 list
一样微不足道:
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)
时间内 运行。
reduce 适用于任意数量的标签。
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]]
好的,在 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)