2010-03-06 12 views
26

Mam listę, która ma powtarzające się elementy i chcę listę unikalnych przedmiotów z ich częstotliwością.Jak uzyskać wartości unikatowe z odpowiednim wystąpieniem, można liczyć z listy w Pythonie?

Na przykład mam ["a", "a", "b", "b", "b"] i chcę [("a", 2), ("b", 3) ]

Szukasz prostego sposobu na zrobienie tego bez podwójnej pętli.

+1

Tak wiesz .. Odpowiedź, którą zaakceptowałeś, narusza twoje "bez podwójnej pętli" Traint. (Jestem tutaj komentarzem, aby otrzymać powiadomienie :-). – Tom

+0

Zgadzam się. Dzięki, Tom. –

+0

Czy możesz też nieco wyjaśnić swoje pytanie? Czy twoje produkty są zawsze zgrupowane? Czy mogą pojawić się w dowolnej kolejności na liście? – Tom

Odpowiedz

10

Jeśli elementy są grupowane (tj podobne elementy łączą się w pęczek), najskuteczniejsza metoda do wykorzystania jest itertools.groupby:

>>> [(g[0], len(list(g[1]))) for g in itertools.groupby(['a', 'a', 'b', 'b', 'b'])] 
[('a', 2), ('b', 3)] 
+0

@ Tom: Mam świadomość tego ograniczenia. Kiedy elementy są pogrupowane, jednak "groupby" jest efektywnym i preferowanym podejściem. –

+1

Powinieneś to wyjaśnić ... zauważ, że ograniczenie w pytaniu mówi "Mam listę, która ma powtarzające się elementy" ... lista OP dał był tylko przykład. Nie sądzę, aby to rozwiązanie było wystarczająco ogólne. Jeśli OP określi, że lista wejściowa zawsze zawierała elementy pogrupowane, zgadzam się. – Tom

+0

@Tom: masz rację - zaktualizowałem odpowiedź (BTW założyłem z jego "powtarzających się pozycji", że są zgrupowane) –

54

Kiedy Python 2.7 wychodzi można użyć jej collections.Counter class

inaczej zobaczyć counter receipe

Pod Pythona 2.7a3

from collections import Counter 
input = ['a', 'a', 'b', 'b', 'b'] 
c = Counter(input) 

print(c.items()) 

wyjście jest

[('a', 2), ('b', 3)]

+0

Hej, chociaż python 2.7 nie pomaga teraz PO ... +1! Klasa collections.Counter jest interesująca i wydaje mi się dobrym skrótem do dostarczonego rozwiązania. (Ma też kilka fajnych dodatków). Ta odpowiedź jest z pewnością taka, którą ludzie będą chcieli przeczytać w przyszłości. Powinieneś zaktualizować przykład użycia. – Tom

2

wiem, że to nie jest jedno-liner ... ale do mnie Lubię go, bo to dla mnie jasne, że możemy przejść nad początkowej listy wartości raz (zamiast dzwonić na nią liczyć):

>>> from collections import defaultdict 
>>> l = ['a', 'a', 'b', 'b', 'b'] 
>>> d = defaultdict(int) 
>>> for i in l: 
... d[i] += 1 
... 
>>> d 
defaultdict(<type 'int'>, {'a': 2, 'b': 3}) 
>>> list(d.iteritems()) 
[('a', 2), ('b', 3)] 
>>> 
1

Innym sposobem na to byłoby

mylist = [1, 1, 2, 3, 3, 3, 4, 4, 4, 4] 
mydict = {} 
for i in mylist: 
    if i in mydict: mydict[i] += 1 
    else: mydict[i] = 1 

następnie uzyskać listę krotek,

mytups = [(i, mydict[i]) for i in mydict] 

Dotyczy to tylko raz na liście, ale nie musi przechodzić słownika raz, jak również. Jednakże, biorąc pod uwagę, że istnieje wiele duplikatów na liście, słownik powinien być o wiele mniejszy, a więc szybszy do przechodzenia.

Niemniej jednak, niezbyt ładny lub zwięzły fragment kodu, przyznaję.

+0

To jest identyczne w duchu z moim rozwiązaniem ... z wyjątkiem defaultdict konsoliduje pierwszą część (ponieważ nie musisz sprawdzać istnienia) i lista (mydict.iteritems()) jest krótsza niż zrozumienie listy. – Tom

+0

'mytups = mydict.items()' jest prostszym sposobem na uzyskanie listy krotek. – PaulMcG

+0

Dzięki @Paul i @Tom. Wygląda na to, że zawsze istnieje lepszy sposób na zrobienie czegoś w Pythonie. :) – Aaron

3

"Droga starej szkoły".

>>> alist=['a', 'a', 'b', 'b', 'b'] 
>>> d={} 
>>> for i in alist: 
... if not d.has_key(i): d[i]=1 #also: if not i in d 
... else: d[i]+=1 
... 
>>> d 
{'a': 2, 'b': 3} 
10
>>> mylist=['a', 'a', 'b', 'b', 'b'] 
>>> [ (i,mylist.count(i)) for i in set(mylist) ] 
[('a', 2), ('b', 3)] 
1

Rozwiązanie bez mieszaja:

def lcount(lst): 
    return reduce(lambda a, b: a[0:-1] + [(a[-1][0], a[-1][1]+1)] if a and b == a[-1][0] else a + [(b, 1)], lst, []) 

>>> lcount([]) 
[] 
>>> lcount(['a']) 
[('a', 1)] 
>>> lcount(['a', 'a', 'a', 'b', 'b']) 
[('a', 3), ('b', 2)] 
1

Konwersja dowolnej struktury danych na serię pandy s:

KOD:

for i in sort(s.value_counts().unique()): 
    print i, (s.value_counts()==i).sum() 
Powiązane problemy