“Splitting” l'uscita di un RLE (groupby) in funzione di un valore definito ( “carattere” per dividere il RLE on)
Domanda
Si consideri la "stringa" (trattare come una serie di cifre)
0 0 1 8 8 8 1 0
Il RLE ( "groupby") è il seguente:
[(0,2), (1, 1), (8,3), (1, 1), (0, 1)]
Abbiamo poi arricchire il RLE sopra con la somma delle lunghezze di esecuzione degli elementi precedenti.
Quindi, la versione arricchita di quanto sopra diventa:
[(0, (0,2)), (0+2, (1, 1)), (0+2+1, (8,3)), (0+1+2+3, (1, 1)), (0+1+2+3+1, (0, 1))]
La scissione "stringa" on 1:
0 0 , 8 8 8 , 0
Split RLE il 1
[(0,2)] , [(8,3)] , [(0, 1)]
La scissione "stringa" in data 8:
0 0 1 , , , 1 0
Split RLE 8
[(0,2), (1, 1)] , , , [(1, 1), (0, 1)]
Nota: Nel mio esempio, ho citato il "RLE divisa su Z" liste senza di loro arricchimento. Questo non sarebbe stato così. Li ho lasciati fuori per ridurre l'ingombro. Ad esempio, il "split RLE il 1" in realtà dovrebbe essere trattato come:
[(0, (0,2))] , [(0+2+1, (8,3))] , [(0+1+2+3+1, (0, 1)]
Come posso realizzare questo "RLE split" su Z (= 1, 8; in questo caso)
E 'bene lasciare fuori array vuoti (dopo la divisione).
Forse un elenco intelligente comp.? (Sembra un po 'più facile da risolvere con un ciclo for con un accodamento nidificato all'interno)
Soluzione
Proprio per mostrare il modo in cui, vi consiglio vivamente di non utilizzare questo
"elegante" brutto modo:
>>> data
[0, 0, 1, 8, 8, 8, 4, 4, 1, 0]
>>> def fromDataToSplitRLE(dat,n):
RLE=[(k,len(tuple(g))) for k,g in itertools.groupby(dat)]
tmp=tuple(zip(*RLE))
return [list(g) for k,g in itertools.groupby((zip((sum(tmp[1][:i]) for i in range(len(tmp[1]))) ,(zip(*tmp)))),lambda x:x[1][0]!=n) if k]
>>> fromDataToSplitRLE(data,1)
[[(0, (0, 2))], [(3, (8, 3)), (6, (4, 2))], [(9, (0, 1))]]
Altri suggerimenti
import itertools
def get_rle(list_of_digits, split_on=None):
count = 0
rle = []
active_group = []
rle_app = rle.append
for item, group in itertools.groupby(list_of_digits):
L = len(list(group))
if item == split_on:
rle_app(active_group)
active_group = []
else:
active_group.append((count, (item, L)))
count += L
rle_app(active_group)
return rle
list_of_digits = map(int, '0 0 1 8 8 8 1 0'.split())
print get_rle(list_of_digits)
print get_rle(list_of_digits, 8)
print get_rle(list_of_digits, 1)
aaron@aaron-laptop:~/code/tmp$ python rle.py
[[(0, (0, 2)), (2, (1, 1)), (3, (8, 3)), (6, (1, 1)), (7, (0, 1))]]
[[(0, (0, 2)), (2, (1, 1))], [(6, (1, 1)), (7, (0, 1))]]
[[(0, (0, 2))], [(3, (8, 3))], [(7, (0, 1))]]