如何在列表中查找重复值并合并它们
How to find duplicate values in a list and merge them
所以基本上例如你有一个像这样的列表:
l = ['a','b','a','b','c','c']
输出应该是:
[['a','a'],['b','b'],['c','c']]
所以基本上把重复的值放在一个列表中,
我试过了:
l = ['a','b','a','b','c','c']
it=iter(sorted(l))
next(it)
new_l=[]
for i in sorted(l):
new_l.append([])
if next(it,None)==i:
new_l[-1].append(i)
else:
new_l.append([])
但是不管用,即使有用也不会高效
排序列表然后使用 itertools.groupby
:
>>> from itertools import groupby
>>> l = ['a','b','a','b','c','c']
>>> [list(g) for _, g in groupby(sorted(l))]
[['a', 'a'], ['b', 'b'], ['c', 'c']]
编辑:这可能不是最快的方法,一般情况下排序的时间复杂度为 O(n log n),并非所有解决方案都需要(参见评论)
您可以使用 collections.Counter
:
from collections import Counter
[[k] * c for k, c in Counter(l).items()]
这个returns:
[['a', 'a'], ['b', 'b'], ['c', 'c']]
%%timeit
比较
- 给定一个包含 100000 个值的样本数据集,此答案是最快的方法。
from collections import Counter
l = ['a','b','a','b','c','c']
c = Counter(l)
print([[x] * y for x, y in c.items()])
# [['a', 'a'], ['b', 'b'], ['c', 'c']]
这是 functional solution via itertools.groupby
。由于需要排序,因此时间复杂度为 O(n log n).
from itertools import groupby
from operator import itemgetter
L = ['a','b','a','b','c','c']
res = list(map(list, map(itemgetter(1), groupby(sorted(L)))))
[['a', 'a'], ['b', 'b'], ['c', 'c']]
语法很繁琐,因为 Python 不提供本机函数组合。这由第 3 方库 toolz
:
支持
from toolz import compose
foo = compose(list, itemgetter(1))
res = list(map(foo, groupby(sorted(L))))
可能不是最有效的,但这是可以理解的:
l = ['a','b','a','b','c','c']
dict = {}
for i in l:
if dict[i]:
dict[i] += 1
else:
dict[i] = 1
new = []
for key in list(dict.keys()):
new.append([key] * dict[key])
另一种方法是使用 zip
方法。
l = ['a','b','a','b','c','c','b','c', 'a']
l = sorted(l)
grouped = [list(item) for item in list(zip(*[iter(l)] * l.count(l[0])))]
输出
[['a', 'a', 'a'], ['b', 'b', 'b'], ['c', 'c', 'c']]
l = ['a','b','a','b','c','c']
want = []
for i in set(l):
want.append(list(filter(lambda x: x == i, l)))
print(want)
我使用列表理解的解决方案是(l 是一个列表):
[l.count(x) * [x] for x in set(l)]
- set(l) 将检索出现在 l 中的所有元素,没有 重复项
- l.count(x) 将 return 特定元素 x 在给定列表中出现的次数 l
- * 运算符 创建一个新列表,列表中的元素(在本例中为 [x])重复指定的次数(此处l.count(x)为次数)
所以基本上例如你有一个像这样的列表:
l = ['a','b','a','b','c','c']
输出应该是:
[['a','a'],['b','b'],['c','c']]
所以基本上把重复的值放在一个列表中,
我试过了:
l = ['a','b','a','b','c','c']
it=iter(sorted(l))
next(it)
new_l=[]
for i in sorted(l):
new_l.append([])
if next(it,None)==i:
new_l[-1].append(i)
else:
new_l.append([])
但是不管用,即使有用也不会高效
排序列表然后使用 itertools.groupby
:
>>> from itertools import groupby
>>> l = ['a','b','a','b','c','c']
>>> [list(g) for _, g in groupby(sorted(l))]
[['a', 'a'], ['b', 'b'], ['c', 'c']]
编辑:这可能不是最快的方法,一般情况下排序的时间复杂度为 O(n log n),并非所有解决方案都需要(参见评论)
您可以使用 collections.Counter
:
from collections import Counter
[[k] * c for k, c in Counter(l).items()]
这个returns:
[['a', 'a'], ['b', 'b'], ['c', 'c']]
%%timeit
比较
- 给定一个包含 100000 个值的样本数据集,此答案是最快的方法。
from collections import Counter
l = ['a','b','a','b','c','c']
c = Counter(l)
print([[x] * y for x, y in c.items()])
# [['a', 'a'], ['b', 'b'], ['c', 'c']]
这是 functional solution via itertools.groupby
。由于需要排序,因此时间复杂度为 O(n log n).
from itertools import groupby
from operator import itemgetter
L = ['a','b','a','b','c','c']
res = list(map(list, map(itemgetter(1), groupby(sorted(L)))))
[['a', 'a'], ['b', 'b'], ['c', 'c']]
语法很繁琐,因为 Python 不提供本机函数组合。这由第 3 方库 toolz
:
from toolz import compose
foo = compose(list, itemgetter(1))
res = list(map(foo, groupby(sorted(L))))
可能不是最有效的,但这是可以理解的:
l = ['a','b','a','b','c','c']
dict = {}
for i in l:
if dict[i]:
dict[i] += 1
else:
dict[i] = 1
new = []
for key in list(dict.keys()):
new.append([key] * dict[key])
另一种方法是使用 zip
方法。
l = ['a','b','a','b','c','c','b','c', 'a']
l = sorted(l)
grouped = [list(item) for item in list(zip(*[iter(l)] * l.count(l[0])))]
输出
[['a', 'a', 'a'], ['b', 'b', 'b'], ['c', 'c', 'c']]
l = ['a','b','a','b','c','c']
want = []
for i in set(l):
want.append(list(filter(lambda x: x == i, l)))
print(want)
我使用列表理解的解决方案是(l 是一个列表):
[l.count(x) * [x] for x in set(l)]
- set(l) 将检索出现在 l 中的所有元素,没有 重复项
- l.count(x) 将 return 特定元素 x 在给定列表中出现的次数 l
- * 运算符 创建一个新列表,列表中的元素(在本例中为 [x])重复指定的次数(此处l.count(x)为次数)