2014-11-09 2 views
1

Я довольно новичок в Python, так что извините, если это наивный вопрос ... Я искал вокруг, но не смог найти изящный ответ для этого ... В collections.Counter , метод most_common(n) возвращает только n наиболее часто используемых элементов в списке. Мне нужно именно это, но мне нужно включить равные подсчеты.Python collections.Counter: most_common ВКЛЮЧАЯ равные числа

from collections import Counter 
test = Counter(["A","A","A","B","B","C","C","D","D","E","F","G","H"]) 
-->Counter({'A': 3, 'C': 2, 'B': 2, 'D': 2, 'E': 1, 'G': 1, 'F': 1, 'H': 1}) 
test.most_common(2) 
-->[('A', 3), ('C', 2) 

я должен был бы [('A', 3), ('B', 2), ('C', 2), ('D', 2)] , так как они имеют одинаковое количество при п = 2 для этого случая ...

Надеюсь, вы умный решение.

P.S. Мои реальные данные о коде ДНК и могут быть довольно большими. Мне нужно, чтобы он был несколько эффективным.

Спасибо за вашу помощь ... Карел

ответ

2

Вы можете сделать что-то вроде этого:

from itertools import takewhile 

def get_items_upto_count(dct, n): 
    data = dct.most_common() 
    val = data[n-1][1] #get the value of n-1th item 
    #Now collect all items whose value is greater than or equal to `val`. 
    return list(takewhile(lambda x: x[1] >= val, data)) 

test = Counter(["A","A","A","B","B","C","C","D","D","E","F","G","H"]) 

print get_items_upto_count(test, 2) 
#[('A', 3), ('C', 2), ('B', 2), ('D', 2)] 
+0

у вас есть опечатка, пожалуйста, исправить, он должен быть 'get_item_upto_count (тест, 2) ' – Anzel

+0

Почему бы не просто взять фрагмент из n элементов, а принять, когда следующий равен последнему элементу n фрагмента? –

+0

@PadraicCunningham Возьмите кусочек чего? –

0

Для небольших наборов, просто написать простой генератор:

>>> test = Counter(["A","A","A","B","B","C","C","D","D","E","F","G","H"]) 
>>> g=(e for e in test.most_common() if e[1]>=2) 
>>> list(g) 
[('A', 3), ('D', 2), ('C', 2), ('B', 2)] 

Для большего набора , используйте ifilter (или просто используйте filter на Python 3):

>>> list(ifilter(lambda t: t[1]>=2, test.most_common())) 
[('A', 3), ('C', 2), ('B', 2), ('D', 2)] 

Или, так как most_common уже заказаны, просто использовать для петли и разорвать на желаемом состоянии в генераторе:

def fc(d, f): 
    for t in d.most_common(): 
     if not f(t[1]): 
      break 
     yield t 

>>> list(fc(test, lambda e: e>=2)) 
[('A', 3), ('B', 2), ('C', 2), ('D', 2)]