“División” la salida de un RLE (GroupBy) en función de un valor definido (el “carácter” para dividir el RLE en)
Pregunta
Considere el "string" (lo tratan como una serie de dígitos)
0 0 1 8 8 8 1 0
La RLE ( "GroupBy") es:
[(0,2), (1, 1), (8,3), (1, 1), (0, 1)]
A continuación, enriquecer el RLE anterior con la suma de las longitudes de secuencia de los elementos anteriores.
Por lo tanto, la versión enriquecida de lo anterior se convierte en:
[(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 "cadena" dividida en 1:
0 0 , 8 8 8 , 0
Split RLE en 1
[(0,2)] , [(8,3)] , [(0, 1)]
La "cadena" dividida en 8:
0 0 1 , , , 1 0
RLE dividida en 8
[(0,2), (1, 1)] , , , [(1, 1), (0, 1)]
Nota: En los ejemplos, he citado la "fracción de RLE en Z" listas sin enriqueciéndolos. Esto no sería así. Los dejé a cabo para reducir el desorden. Por ejemplo, el "split RLE en 1" en realidad debería ser tratada como:
[(0, (0,2))] , [(0+2+1, (8,3))] , [(0+1+2+3+1, (0, 1)]
¿Cómo puedo lograr este "split RLE" en Z (= 1, 8; en este caso)
Está bien dejar fuera matrices vacías (después de la división).
Tal vez una lista inteligente comp.? (Parece un poco más fácil de resolver con un bucle con un append anidado dentro)
Solución
Sólo para la demostración de la manera cómo, yo recomiendo que no use este
"elegante" fea manera:
>>> 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))]]
Otros consejos
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))]]