Girişinizde çift sayıda öğe var:
say elems <1 1 0 2 0 2 1 2 2 2 4 4 3 3>; # 14
Kişisel grep
bloğu iki öğe her zaman tüketir:
{$^a eq $^b}
Dolayısıyla, bir öğe ekler veya kaldırırsanız, blok sonunda kalan tek bir öğe üzerinde çalıştırıldığında karşılaştığınız hatayı alırsınız.
Sorununuzu çözmenin birçok yolu vardır.
Ancak aynı zamanda üst üste binmeye izin verme seçeneğini de sordunuz; örneğin, (2 2)
sekansla 2 2 2
karşılaşıldığında iki alt liste alırsınız . Ve benzer bir şekilde, muhtemelen sıfır olmayan iki eşleşme görmek istiyorsunuz, giriş gibi:
<1 2 2 3 3 4>
Bu yüzden bu sorunlarla da ilgilenen çözümlere odaklanacağım.
Ekstra sorunlarla başa çıkmak için çözüm alanının daralmasına rağmen, çözümleri işlevsel olarak ifade etmenin hala birçok yolu vardır.
Sonuna biraz daha kod eklemenin bir yolu:
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
.rotor
Yöntem, alt-listeleri, aynı uzunlukta, her bir listesini gösteren bir listeyi dönüştürür. Örneğin, say <1 2 3 4> .rotor: 2
görüntüler ((1 2) (3 4))
. Uzunluk bağımsız değişkeni bir çiftse, anahtar uzunluktur ve değer sonraki çifti başlatmak için bir ofsettir. Ofset negatifse alt liste çakışması alırsınız. Böylece say <1 2 3 4> .rotor: 2 => -1
görüntülenir ((1 2) (2 3) (3 4))
.
.flat
Yöntem "derecede düzeltilir" onun invocant. Örneğin, say ((1,2),(2,3),(3,4)) .flat
görüntüler (1 2 2 3 3 4)
.
Yukarıdaki çözümü yazmanın belki de daha okunabilir bir yolu, tarafından döndürülen alt listelerin çıkarılması flat
ve kullanılması .[0]
ve .[1]
dizine eklenmesi olacaktır rotor
:
say @s .rotor( 2 => -1 ) .grep: { .[0] eq .[1] }
Ayrıca herhangi bir alt liste boyutu için genelleştirilen başka bir varyasyon için Elizabeth Mattijsen'in yorumuna bakın.
Daha genel bir kodlama desenine ihtiyacınız varsa aşağıdaki gibi bir şey yazabilirsiniz:
say @s .pairs .map: { .value xx 2 if .key < @s - 1 and [eq] @s[.key,.key+1] }
.pairs
Bir listedeki bir yöntem çiftlerinin bir listesini, kendi invocant listesindeki elemanlarının her birine tekabül eden her bir çift döner. .key
Her bir çiftin invocant listedeki elementin endeksidir; .value
elemanın bir değerdir.
.value xx 2
yazılabilirdi .value, .value
. (Bkz xx
.)
@s - 1
@s
eksi 1'deki eleman sayısıdır .
[eq]
İçinde [eq] list
bir olduğunu azalma .
Bitişik eşit öğeleri neyin oluşturduğuna karar vermek için metin deseni eşleşmesine ihtiyacınız varsa, giriş listesini bir dizeye dönüştürebilirsiniz, eşleşme listesi oluşturan eşleşme zarflarından birini kullanarak eşleştirin, ardından sonuçtaki eşleşme listesinden istediğiniz eşlemeyle eşleştirin sonuç. Çakışanlarla eşleşmek için (örn 2 2 2
. ((2 2) (2 2))
Kullanımdaki sonuçlar :ov
:
say @s .Str .match( / (.) ' ' $0 /, :ov ) .map: { .[0].Str xx 2 }
2 2 2 2
3(2 2)
s yazdırır . Yöntemi hiç duymadımrotor
Başlangıçta yönteme geldimsquish
ve bunun gibi özelliklere veya argümanlara sahip olup olmadığını kontrol ettim,@s.squish(:length 2, :multiple_instances yes)
ancak bu tür özelliklere sahip değildi ve görev için uygun değildi. İle karşılaştırıldığındasquish
,rotor
oldukça uygun görünüyor. Aslında bu tür bir işlem için en uygun olanı bile olabilir.