2016-06-11 6 views
5

Così, per esempio se ho le listeTrova numero di elementi consecutivi che sono gli stessi prima che cambino

a = [1,1,1,2,2] 
b = [1,1,2,2,2] 
c = [2,1,1,1,1] 

vorrei ottenere la più lunga striscia del primo elemento della lista, così per esempio a darebbe 3, b darebbe 2 e c darebbe 1. So che potrei creare un ciclo while e contare la striscia in questo modo, ma mi stavo chiedendo se c'è un modo più elegante per fare questo?

+0

se si desidera contare tutte le istanze del primo elemento quindi è possibile utilizzare a.Count ([0]) – amitnair92

+0

La frase "più lunga '* * striscia' del primo elemento" è un un po 'ambiguo: se la risposta a '[1,1,1,2,2,1,1,1,1]' è 3 o 4. – ninjagecko

risposta

6

si potrebbe fare qualcosa di simile:

numStreak = ([a[0] == n for n in a]+[False]).index(False) 

(questo rende anche sicuro che se tutti gli elementi sono come il primo elemento, l'indice non restituisce il valore corretto)

UPDATE: una più efficiente (ma meno elegante?) versione

from itertools import takewhile 
len([1 for _ in takewhile(lambda x:x==a[0], a)]) 

o un po 'meglio (UPDATE 2) @ suggerimento vaultah:

sum(1 for _ in takewhile(lambda x:x==a[0], a)) 
+2

Questo è molto intelligente ma mi rattrista che itera su tutta la lista anche se la lunghezza è solo 1. –

+0

Ho aggiunto una versione più efficiente ma forse leggermente meno elegante – DomTomCat

+0

Dovrebbe essere 'sum (1 per _ in takewhile (lambda x: x == a [0], a))' – vaultah

3

È possibile utilizzare groupby e sommare quanti articoli sono nel primo gruppo per ciascuna:

a = [1,1,1,2,2] 
b = [1,1,2,2,2] 
c = [2,1,1,1,1] 

from itertools import groupby 

for l in [a,b,c]: 
    print(sum(1 for _ in next(groupby(l), [[], []],)[1])) 

o utilizzando TakeWhile:

from itertools import takewhile 

for l in [a, b, c]: 
    print(sum((1 for _ in takewhile(lambda x: x == l[0], l)))) 

Se i dati sono sempre una lista, tuple etc. . nel groupby è possibile verificare la presenza di un valore Falsey invece di impostare un default in next(..:

012.351.
for l in [a, b, c]: 
    print(sum(1 for _ in next(groupby(l))[1]) if l else 0) 
+0

Non capisco bene il '[[], []]' parte. Che cosa sta facendo? – DSM

+0

@DSM, se è stato passato un iterabile vuoto si otterrebbe un errore 'StopIteration' –

+0

Ah, ok, vedo cosa stai facendo ora. Se sappiamo che abbiamo sequenze probabilmente aggiungerei semplicemente "if l else 0" alla fine, ma ciò non gestirà il caso di un iterabile generale. – DSM

0

Si potrebbe utilizzare NumPy:

>>> import numpy as np 
>>> a = [1,1,1,2,2] 
>>> b = [1,1,2,2,2] 
>>> c = [2,1,1,1,1] 
>>> def runs(data): 
... return np.split(data, np.where(np.diff(data) != 0)[0]+1) 
... 
>>> for e in a,b,c: 
... runs(np.array(e)) 
... 
[array([1, 1, 1]), array([2, 2])] 
[array([1, 1]), array([2, 2, 2])] 
[array([2]), array([1, 1, 1, 1])] 

Poi basta prendere la lunghezza della prima manche:

>>> for e in a,b,c: 
... len(runs(np.array(e))[0]) 
... 
3 
2 
1 

Oppure, in Python, basta usare un while ciclo:

>>> def r(a): 
... i=1 
... while a[0]==a[i]: i+=1 
... return i 
... 
>>> r(a) 
3 
>>> r(b) 
2 
>>> r(c) 
1 
1

Una fodera per la strada? Prendi la mira ...

a = [5,5,5,5,8] 
list(np.ediff1d(a)).count(0)+1 
>>> 4 
Problemi correlati