Як знайти повторювані значення та об'єднати їх? - пітон

Отже, наприклад, у вас є список таких:

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([])

Але не працює, і якщо він спрацьовує, він не буде ефективним

3

8 Відповіді

Сортувати список, а потім використовувати 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']]

EDIT: це, мабуть, не найшвидший підхід, сортування O (n log n) тимчасової складності для середнього випадку і не обов'язкове для всіх рішень (див. Коментарі)

5
додано
@Chris_Rands або якщо версія Python запам'ятовує порядок вставки dict, тобто 3.6 і вище.
додано Автор timgeb, джерело
@blhsing Так, я знаю, я насправді не впевнений, що це найкраще рішення, це була моя перша думка (треба бути швидким на SO), я відкладу судження до тесту timeit
додано Автор Chris_Rands, джерело
@blhsing так, ви просто сказали, що, я згоден :)
додано Автор Chris_Rands, джерело
@ U9-Forward Thanks, але я не переконаний, що це найкращий спосіб, рішення Austin або Blhsing можуть бути швидше, і зберігатиме замовлення, якщо додано рецепт OrderedCounter
додано Автор Chris_Rands, джерело
@timgeb дійсно або 3.7 і вище для гарантії для всіх реалізацій python
додано Автор Chris_Rands, джерело
@ timgeb BTW я думаю, що причина, я думав про це перше і здається настільки інтуїтивним, що це слідувати типовим командного рядка (UNIX) шаблон сортування | uniq -c
додано Автор Chris_Rands, джерело
Спасибі це працює, дивно, дякую
додано Автор U8-Forward, джерело
Прийнято .., не розуміє, що itertools.groupby може зробити це багато чого :-)
додано Автор U8-Forward, джерело
@Chris_Rands Відомо, що функція Python sorted має середню часову складність O (n log n).
додано Автор blhsing, джерело
Це вимагає середньої часової складності O (n log n), однак.
додано Автор blhsing, джерело

Використовуйте collections.Counter :

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']]
3
додано
Це найкраще рішення. Легко читається і не вимагає сортування (якщо ви використовуєте версію Python, де dicts пам'ятають порядок вставки).
додано Автор timgeb, джерело
@timgeb Домовилися! Хоча, звичайно, сортування і збереження порядку вставки і не завжди збирається виробляти один і той же висновок (хоча вони і роблять для цих даних); не знаю, що ОР хоче напевно
додано Автор Chris_Rands, джерело
Працює теж, приємно
додано Автор U8-Forward, джерело

Ви можете використовувати collections.Counter :

from collections import Counter
[[k] * c for k, c in Counter(l).items()]

Це повертає:

[['a', 'a'], ['b', 'b'], ['c', 'c']]
3
додано
Працює теж, приємно
додано Автор U8-Forward, джерело
Правильно, правильно.
додано Автор U8-Forward, джерело
Зауважте, що Counter() має середню складність часу O (n).
додано Автор blhsing, джерело

Нижче наведено розділ функціональний за допомогою 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 не пропонує рідну композицію функцій. Це підтримується бібліотекою третіх сторін toolz :

from toolz import compose

foo = compose(list, itemgetter(1))
res = list(map(foo, groupby(sorted(L))))
1
додано
Працює теж, приємно
додано Автор U8-Forward, джерело
l = ['a','b','a','b','c','c']

want = []
for i in set(l):
    want.append(list(filter(lambda x: x == i, l)))
print(want)    
1
додано
складність часу O (n ** 2)
додано Автор timgeb, джерело
Працює теж, приємно
додано Автор U8-Forward, джерело

Інший підхід полягає у використанні методу 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']]
1
додано
Працює теж, приємно
додано Автор U8-Forward, джерело

Напевно, не найефективніше, але це зрозуміло:

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])
1
додано
Працює теж, приємно
додано Автор U8-Forward, джерело

Також я зрозумів це:

print([[i]*l.count(i) for i in sorted(set(l),key=l.index)])

Що також працює

0
додано
ІТ КПІ - Python
ІТ КПІ - Python
625 учасників

Канал обговорень про всякі штуки зі світу пайтону. Прохання: 0. мати повагу одне до одного; 1. не матюкатися в сторону людей; 2. не захламляти тред повідомленнями по одному слову;