2009-05-19 10 views
10

se ho una lista in Python comeCome si calcola il maggior numero di ripetizioni in un elenco?

[1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1] 

Come faccio a calcolare il maggior numero di ripetizioni per ogni elemento? In questo caso, 2 viene ripetuto un massimo di 4 volte e 1 viene ripetuto un massimo di 3 volte.

C'è un modo per fare ciò ma anche registrare l'indice al quale è iniziata la corsa più lunga?

+0

Sembra che si stia cercando la corsa più lunga nell'elenco; potresti voler modificare la tua domanda per renderla chiara. – las3rjock

+2

Specificamente la corsa più lunga di ogni numero – Sparr

+0

Sì Sparr che è corretto. C'è un modo per farlo, ma anche registrare l'indice in cui è iniziata la corsa più lunga? – hekevintran

risposta

42

Usa groupby, esso elementi del gruppo di valore:

from itertools import groupby 
group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]) 
print max(group, key=lambda k: len(list(k[1]))) 

Ed ecco il codice in azione:

>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]) 
>>> print max(group, key=lambda k: len(list(k[1]))) 
(2, <itertools._grouper object at 0xb779f1cc>) 
>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3]) 
>>> print max(group, key=lambda k: len(list(k[1]))) 
(3, <itertools._grouper object at 0xb7df95ec>) 

Da documentazione python:

L'operazione di groupby() è simile a al filtro uniq in Unix. Si genera una pausa o nuovo gruppo ogni volta che il valore della funzione chiave cambia

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B 
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D 

Se si desidera anche l'indice della pista più lunga è possibile effettuare le seguenti operazioni:

group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3]) 
result = [] 
index = 0 
for k, g in group: 
    length = len(list(g)) 
    result.append((k, length, index)) 
    index += length 

print max(result, key=lambda a:a[1]) 
+0

+1 - 'groupby' è fatto su misura per questo. –

+0

C'è un modo per fare questo e anche registrare l'indice al quale è iniziata la corsa più lunga? Grazie! – hekevintran

+0

Ho aggiornato la risposta con una soluzione per ottenere anche l'indice –

0

Questo codice sembra funzionare:

l = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1] 
previous = None 

# value/repetition pair 
greatest = (-1, -1) 
reps = 1 

for e in l: 
    if e == previous: 
     reps += 1 
    else: 
     if reps > greatest[1]: 
      greatest = (previous, reps) 

     previous = e 
     reps = 1 

if reps > greatest[1]: 
    greatest = (previous, reps) 

print greatest 
+0

+1 per avermi picchiato. – geowa4

+3

non è quello che chiede OP – SilentGhost

+0

OPPURE ha dato il test case ... che i risultati non corrispondono ... –

0

userei un HashMap di elemento per contrastare.

Ogni volta che si visualizza una successione di "chiave", incrementare il valore del contatore. Se colpisci un nuovo elemento, imposta il contatore su 1 e continua. Alla fine di questa ricerca lineare, si dovrebbe avere il conteggio della successione massimo per ciascun numero.

3

Passare in rassegna l'elenco, tenere traccia del numero corrente, quante volte è stato ripetuto e confrontarlo al maggior numero di volte in cui si è visto ripetere quel numero.

Counts={} 
Current=0 
Current_Count=0 
LIST = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1] 
for i in LIST: 
    if Current == i: 
     Current_Count++ 
    else: 
     Current_Count=1 
     Current=i 
    if Current_Count>Counts[i]: 
     Counts[i]=Current_Count 
print Counts 
1

Se lo si desidera per il solo qualsiasi elemento (ovvero l'elemento con la maggior parte delle ripetizioni), è possibile utilizzare:

def f((v, l, m), x): 
    nl = l+1 if x==v else 1 
    return (x, nl, max(m,nl)) 

maxrep = reduce(f, l, (0,0,0))[2]; 

Conta solo ripetizioni continue (il risultato per [1,2,2,2,1,2] è 3) e registra solo l'elemento con il numero massimo.

Edit: definizione Realizzato in Fa po 'più breve ...

+0

Sembra simile a un sacco di roba Perl? ;) –

1

Questa è la mia soluzione:

def longest_repetition(l): 
    if l == []: 
     return None 

    element = l[0] 
    new = [] 
    lar = [] 

    for e in l:    
     if e == element: 
      new.append(e) 
     else: 
      if len(new) > len(lar): 
       lar = new 
      new = [] 
      new.append(e) 
      element = e 
    if len(new) > len(lar): 
     lar = new  
    return lar[0] 
1

-È possibile creare nuova copia della lista, ma con valori unici e una corrispondente colpi elenco.

-Quando ottieni il numero massimo di hit e ottieni dal tuo indice l'oggetto più ripetuto.

oldlist = ["A", "B", "E", "C","A", "C","D","A", "E"] 
newlist=[] 
hits=[] 
for i in range(len(oldlist)): 
    if oldlist[i] in newlist: 
     hits[newlist.index(oldlist[i])]+= 1 
    else: 
     newlist.append(oldlist[i]) 
     hits.append(1); 
#find the most repeated item 
temp_max_hits=max(hits) 
temp_max_hits_index=hits.index(temp_max_hits) 
print(newlist[temp_max_hits_index]) 
print(temp_max_hits) 

Ma io non so è questo il modo più veloce per farlo o non ci sono soluzione più veloce. Se pensi ci sia una soluzione più veloce o più efficiente, ti preghiamo gentilmente di informarci.

Problemi correlati