Il y a un nombre pair d'éléments dans votre entrée:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
Votre grepbloc consomme à chaque fois deux éléments:
{$^a eq $^b}
Donc, si vous ajoutez ou supprimez un élément, vous obtiendrez l'erreur que vous obtenez lorsque le bloc est exécuté sur le seul élément restant à la fin.
Il existe de nombreuses façons de résoudre votre problème.
Mais vous avez également demandé l'option de permettre le chevauchement, par exemple, vous obtenez deux (2 2)sous-listes lorsque la séquence 2 2 2est rencontrée. Et, dans la même veine, vous voulez probablement voir deux correspondances, pas zéro, avec une entrée comme:
<1 2 2 3 3 4>
Je vais donc me concentrer sur les solutions qui traitent également de ces problèmes.
Malgré le rétrécissement de l'espace des solutions pour traiter les problèmes supplémentaires, il existe encore de nombreuses façons d'exprimer les solutions de manière fonctionnelle.
Une façon qui ajoute juste un peu plus de code à la fin de la vôtre:
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
La .rotorméthode convertit une liste en une liste de sous-listes, chacune de la même longueur. Par exemple, say <1 2 3 4> .rotor: 2s'affiche ((1 2) (3 4)). Si l'argument de longueur est une paire, la clé est la longueur et la valeur est un décalage pour démarrer la paire suivante. Si le décalage est négatif, vous obtenez un chevauchement de sous-liste. say <1 2 3 4> .rotor: 2 => -1Affiche ainsi ((1 2) (2 3) (3 4)).
La .flatméthode "aplatit" son invocant. Par exemple, say ((1,2),(2,3),(3,4)) .flats'affiche (1 2 2 3 3 4).
Une façon peut-être plus lisible d'écrire la solution ci-dessus serait d'omettre flatet d'utiliser .[0]et .[1]d'indexer dans les sous-listes renvoyées par rotor:
say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }
Voir aussi le commentaire d'Elizabeth Mattijsen pour une autre variation qui se généralise pour toute taille de sous-liste.
Si vous aviez besoin d'un modèle de codage plus général, vous pourriez écrire quelque chose comme:
say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }
La .pairsméthode sur une liste renvoie une liste de paires, chaque paire correspondant à chacun des éléments de sa liste invocante. Le .keyde chaque paire est l'indice de l'élément dans la liste invocante; l' .valueest la valeur de l'élément.
.value xx 2aurait pu être écrit .value, .value. (Voir xx.)
@s - 1est le nombre d'éléments en @smoins 1.
L' [eq]entrée [eq] listest une réduction .
Si vous avez besoin d'une correspondance de modèle de texte pour décider de ce qui constitue des éléments égaux contigus, vous pouvez convertir la liste d'entrée en chaîne, comparez-la à celle-ci en utilisant l'un des adverbes de correspondance qui génèrent une liste de correspondances, puis mappez la liste de correspondances résultante vers la liste souhaitée résultat. Pour correspondre aux chevauchements (par exemple, les 2 2 2résultats d' ((2 2) (2 2))utilisation :ov:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2il imprime 3(2 2)s, ce qui est comme prévu.rotorJe n'ai jamais entendu parler de la méthode.J'ai initialement proposé cettesquishméthode et vérifié si elle avait des fonctionnalités ou des arguments comme,@s.squish(:length 2, :multiple_instances yes)mais elle n'en avait pas et elle n'était pas adaptée à la tâche. Par rapport ausquish,rotorsemble tout à fait en forme. En fait, il pourrait même être le plus adapté à ce type d'opération.