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 grepbloque 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 2se 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 .rotormétodo convierte una lista en una lista de sublistas, cada una de la misma longitud. Por ejemplo, say <1 2 3 4> .rotor: 2pantallas ((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 => -1muestra ((1 2) (2 3) (3 4)).
El .flatmétodo "aplana" a su invocante. Por ejemplo, say ((1,2),(2,3),(3,4)) .flatpantallas (1 2 2 3 3 4).
Una forma quizás más legible de escribir la solución anterior sería omitir flaty 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 .pairsmétodo en una lista devuelve una lista de pares, cada par correspondiente a cada uno de los elementos en su lista de invocadores. El .keyde cada par es el índice del elemento en la lista de invocantes; el .valuees el valor del elemento.
.value xx 2podría haber sido escrito .value, .value. (Ver xx)
@s - 1es el número de elementos en @smenos 1.
El [eq]en [eq] listes 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 2resultados 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ó elsquishmé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,rotorparece bastante en forma. En realidad, incluso podría ser el más apto para este tipo de operación.my $size = 2; say <1 1 0 2 0 2 1 2 2 2 4 4 3 3>.rotor( $size => -$size + 1).grep: { [eq] $_ }# ((1 1) (2 2) (2 2) (4 4) (3 3)) Solo necesita ajustar el$sizepara diferentes longitudes de secuencias.rotorque he agregado han debilitado o fortalecido mi respuesta.rotorsolución,say @s.rotor(2=>-1).grep:{.[0]eq.[1]}es decir, es bienvenida porque es más corta (de 3 a 5 caracteres dependiendo de cómo se cuentan los espacios) y aún se ve decente. Las versiones generalizadas sin elrotormétodo también son bienvenidas porque muestran cómo se usan algunas peculiaridades comoxxy:ov. Así que el problema está muy bien resuelto :)TIMTOWDI!
Aquí hay un enfoque iterativo usando
gather/take.fuente
take ($last, $_)parte es un ejemplo decente sobre el uso delgather and takedúo.