2017-02-19 23 views
2

У меня есть список таких, как это:Pythonic способ найти все элементы с самой высокой частотой?

lst = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4] 

Я хотел бы найти всех элементов, которые встречаются наиболее часто. Поэтому я хотел бы:

most = [1, 3, 5] 

1, 3 и 5 будет происходить самое, что в 4 раза. Что такое быстрый, питонический способ сделать это? Я пробовал методы, показанные здесь:

How to find most common elements of a list?.

Но это только дает мне верх 3, мне нужны все элементы. Спасибо.

+0

Это ответ в ссылке делает срез 'popular_words [: 3 ] ', чтобы возвращать только верхнюю часть 3. Фактический счетчик содержит все итоговые значения, а не только верх 3. – krock

ответ

7

С collections.Counter и списка понимание:

from collections import Counter 

lst = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4] 
r = [x for x, _ in Counter(lst).most_common(3)] 
print(r) 
# [1, 3, 5] 

Вы можете обобщать для значений с самым высоким подсчетом с помощью max на значениях счетчика:

c = Counter(lst) 
m = max(c.values()) 
r = [k for k in c if c[k] == m] 
print(r) 
# [1, 3, 5] 

Для большого итерируемых, эффективна итерации через счетчик и остановитесь, как только необходимые предметы будут приняты, вы можете использовать itertools.takewhile с most_common без каких-либо параметров:

from itertools import takewhile 

c = Counter(lst) 
m = max(c.values()) 
r = [x for x, _ in takewhile(lambda x: x[1]==m, c.most_common())] 
print(r) 
# [1, 3, 5] 

Вы получаете, не имея перебор всех элементов в объекте счетчика, хотя есть некоторые накладные расходы при необходимости сортировки элементов с использованием most_common; поэтому я уверен, что это абсолютно эффективно. Вы можете провести некоторые эксперименты с timeit.

+0

Это работы, но я хотел бы найти ** все ** элементы, которые встречаются наиболее часто, а не только первые 3 . Однако, спасибо. –

+0

@ArjunVasudevan Я обновил для общего случая –

0

Вы можете сделать следующее, если вы хотите печатать все наиболее часто,

from collections import Counter 
    words=[1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4] 
    most= [word for word, word_count in Counter(words).most_common()] 
    print (most) 
>>> 
[1, 3, 5, 4, 2, 6] 

Пожалуйста, обратите внимание, если вы хотите ограничить, вы можете ввести номер внутри most_common() функции. Пример: ...most_common(3)]. Надеюсь, что это ответ на ваш вопрос.

1

Вы также можете получить тот же результат с groupby от itertools модуля и list comprehension таким образом:

from itertools import groupby 

a = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4] 
most_common = 3 
final = [k for k,v in groupby(sorted(a), lambda x: x) if len(list(v)) > most_common] 

Выходные:

print(final) 
>>> [1, 3, 5] 
+1

Ну, это предполагает, что у вас уже есть порог априори –

+0

Да. Это правда. Однако он может распространяться на все случаи. –

Смежные вопросы