2014-01-21 4 views
2

У меня есть список, как этотпитона список количества элементов вхождения и поместить результат в списке

L=['d','f','d','c','c','f','d','f'] 

и я хотел бы подсчитать, сколько d, f и C вхождений в L и сохранить результат как:

R=[['d',3],['f',3],['c',2]] 

Каков наилучший способ (алгоритм)?

ответ

5

Лучший подход (алгоритм) - это не делать это самостоятельно!

>>> from collections import Counter 
>>> L=['d','f','d','c','c','f','d','f'] 
>>> Counter(L) 
Counter({'d': 3, 'f': 3, 'c': 2}) 

Если вы настаиваете на списке:

>>> Counter(L).items() 
[('c', 2), ('d', 3), ('f', 3)] 
2

Я чувствую словарь будет лучше для этого:

>>> from collections import Counter 
>>> L = ['d','f','d','c','c','f','d','f'] 
>>> Counter(L) 
Counter({'d': 3, 'f': 3, 'c': 2}) 

Однако, если вы непреклонны список списков :

>>> L=['d','f','d','c','c','f','d','f'] 
>>> from collections import Counter 
>>> var = Counter(L) 
>>> [[key, value] for key, value in var.items()] 
[['c', 2], ['d', 3], ['f', 3]] 
1
L=['d','f','d','c','c','f','d','f'] 
from collections import Counter 
print Counter(L) 

Выход

Counter({'d': 3, 'f': 3, 'c': 2}) 

Вы можете использовать Counter.most_common метод, чтобы получить результат, как этот

print Counter(L).most_common() 

Выход

[('d', 3), ('f', 3), ('c', 2)] 
1

Возможное решение с использованием itertools.groupby на отсортированного да та

Реализация

from itertools import groupby 
[[k, len(list(v))] for k, v in groupby(sorted(L))] 

Выход

[['c', 2], ['d', 3], ['f', 3]] 

Сравнение производительности

In [9]: L = [choice(ascii_letters) for _ in range(1000)] 

    In [10]: %timeit [[k, len(list(v))] for k, v in groupby(sorted(L))] 
    1000 loops, best of 3: 271 us per loop 

    In [11]: %timeit Counter(L).items() 
    1000 loops, best of 3: 306 us per loop 

Примечание

Следует отметить, что накладные расходы в борьбе решения в хэширования данных, проскакивает сложности сортировки в Tim's Sort

+0

Ваш первый образец является неправильным - вы измеряете время создания строки. На моей машине: оценка списка - 250 us; __Counter__ без __items() __ - 232 us; с __items__ - 239 нас. Удовлетворение списка является самым медленным – volcano

+0

@volcano: я не вижу, создание строки в первом примере :-) – Abhijit

+0

Ну, вы обманули и изменили свой ответ :). , В любом случае, результат, похоже, зависит от реализации. Я запускаю его несколько раз - чистый __Counter__ всегда побеждает. Я думаю, что правило большого пальца - если у вас есть определенный API, чтобы что-то сделать для вас - сделайте это именно так; в большинстве случаев он будет более эффективным – volcano

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