Hay un número par de elementos en su entrada:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
Tu grep
bloque consume dos elementos cada vez:
{$^a eq $^b}
Entonces, si agrega o elimina un elemento, obtendrá el error que obtiene cuando el bloque se ejecuta en el elemento único que queda al final.
Hay muchas formas de resolver su problema.
Pero también preguntó sobre la opción de permitir la superposición, por ejemplo, obtiene dos (2 2)
sublistas cuando 2 2 2
se encuentra la secuencia . Y, en una línea similar, presumiblemente desea ver dos coincidencias, no cero, con entradas como:
<1 2 2 3 3 4>
Así que me enfocaré en soluciones que también aborden esos problemas.
A pesar de la reducción del espacio de solución para tratar los problemas adicionales, todavía hay muchas formas de expresar soluciones funcionalmente.
Una forma que solo agrega un poco más de código al final del tuyo:
my @s = <1 1 0 2 0 2 1 2 2 2 4 4 3 3>;
say grep {$^a eq $^b}, @s .rotor( 2 => -1 ) .flat
El .rotor
método convierte una lista en una lista de sublistas, cada una de la misma longitud. Por ejemplo, say <1 2 3 4> .rotor: 2
pantallas ((1 2) (3 4))
. Si el argumento de longitud es un par, entonces la clave es la longitud y el valor es un desplazamiento para comenzar el siguiente par. Si el desplazamiento es negativo, se superponen las sublistas. Así se say <1 2 3 4> .rotor: 2 => -1
muestra ((1 2) (2 3) (3 4))
.
El .flat
método "aplana" a su invocante. Por ejemplo, say ((1,2),(2,3),(3,4)) .flat
pantallas (1 2 2 3 3 4)
.
Una forma quizás más legible de escribir la solución anterior sería omitir flat
y usar .[0]
e .[1]
indexar en las sublistas devueltas por rotor
:
say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }
Vea también el comentario de Elizabeth Mattijsen para otra variación que generaliza para cualquier tamaño de sublista.
Si necesita un patrón de codificación más general, puede escribir algo como:
say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }
El .pairs
método en una lista devuelve una lista de pares, cada par correspondiente a cada uno de los elementos en su lista de invocadores. El .key
de cada par es el índice del elemento en la lista de invocantes; el .value
es el valor del elemento.
.value xx 2
podría haber sido escrito .value, .value
. (Ver xx
)
@s - 1
es el número de elementos en @s
menos 1.
El [eq]
en [eq] list
es una reducción .
Si necesita una coincidencia de patrón de texto para decidir qué constituye elementos iguales contiguos, puede convertir la lista de entrada en una cadena, hacer coincidir eso con uno de los adverbios de coincidencia que generan una lista de coincidencias, luego asignar desde la lista de coincidencias resultante a la deseada resultado. Para coincidir con superposiciones (por ejemplo, 2 2 2
resultados en ((2 2) (2 2))
uso :ov
:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2
, imprime 3(2 2)
s, que es como se esperaba. Nunca escuché sobre el métodorotor
. Inicialmente se me ocurrió elsquish
método y comprobé si tiene características o argumentos similares,@s.squish(:length 2, :multiple_instances yes)
pero no tenía tales características y no era adecuado para la tarea. En comparación con elsquish
,rotor
parece bastante en forma. En realidad, incluso podría ser el más apto para este tipo de operación.