Dizeden dizine göre bazı karakterler kaldırma (Raku)


15

SSS: Raku'da bir dizeden bazı karakterleri dizinlerine göre nasıl silebilirsiniz?

Diyelim ki 1 ila 3 ve 8 indekslerini kaldırmak istiyorum

xxx("0123456789", (1..3, 8).flat);  # 045679

Yanıtlar:


14

Shnipersons çesidi cevap:

my $a='0123456789';
with $a {$_=.comb[(^* ∖ (1..3, 8).flat).keys.sort].join};
say $a;

Bir satırda:

say '0123456789'.comb[(^* ∖ (1..3, 8).flat).keys.sort].join;

veya bir işlev tarafından çağrılır:

sub remove($str, $a) {
    $str.comb[(^* ∖ $a.flat).keys.sort].join;
}

say '0123456789'.&remove: (1..3, 8);

veya Str'nin arttırılması ile:

use MONKEY-TYPING;
augment class Str {
    method remove($a) {
        $.comb[(^* ∖ $a.flat).keys.sort].join;
    }
};

say '0123456789'.remove: (1..3, 8);

Bu, bence sorunu tamamen çözüyor. Hatırladığınız için teşekkürler \ ve (-) eşdeğerdir. Ben diğer yollarını görmüyorum dilim ben indeksi yok istemiyor ve istediğim endeksleri.
Tinmarino

1
Sen kullanmak zorunda değilsiniz MONKET-TYPINGgibi sadece yöntem yüzen ücretsiz yapmak ve onu ararsanız 'foobar'.&remove: (1..2, 4); (birkaç kez kullanıldığında oluþmuþ bir kompozisyon ile sorunları olabilir)
user0721090601

(bu .&remove
artırmanın

Öneriye ek olarak zenginleştirmeyen varyantı ekledim. Teşekkür ederim.
Sebastian

1
∖ kafa karıştırıcı ve ters eğik çizgi karakteri gibi görünüyor.
Shniperson

12
.value.print if .key  !(elem) (1,2,3,8) for '0123456789'.comb.pairs

9

Çalışmayan bir işlem için son fikrim (aşağıdaki uygulamayı ele alacağım):

Kullanımı:

say '0123456789'[- 1..3, 8 ]; # 045679

Brad'in çözümünün uygulanması, ambalajlanması (bir çeşidi):

multi postcircumfix:<[- ]> (|args) { remove |args }

sub remove( Str:D $str is copy, +@exdices){
    for @exdices.reverse {
        when Int   { $str.substr-rw($_,1) = '' }
        when Range { $str.substr-rw($_  ) = '' }
    }
    $str
}

say '0123456789'[- 1..3, 8 ]; # 045679

Sözdizimi I beyan ettik operatörü kullanmak string[- list-of-indices-to-be-subtracted ]tanıdık kullanarak, yani [...]gösterimi, ancak solda bir dize ve açıldıktan sonra ek bir eksi [indis içerikleri listesi olduğunu belirtmek için exdices ziyade endekslerine .

[Düzenle: Orijinal uygulamamı Brad's ile değiştirdim. Muhtemelen yanlış kafalı çünkü Brad'in belirttiği gibi, çözümü "[exdices] 'in en düşükten en yükseğe doğru olduğunu varsayıyor ve üst üste binme yok." Ve aksi halde vaat etmese de [- ... ]kullanımı çok yakın Bu şekilde. Eğer bu sözdizimi şekeri birisi tarafından kullanılacaksa, muhtemelen Brad'in çözümünü kullanmamalıdırlar. Belki Brad'in yaptığı varsayımı ortadan kaldırmanın bir yolu vardır.]

Bu sözdizimi gibi ama Larry kasten vermedi farkındayım değil kullanımında inşa [...]endeks dizelerine belkide benim dizimi yaygınlaşmasının için uygun değildir. Belki de bazı farklı parantez karakterleri kullanılması daha iyi olurdu. Ama basit bir postcircumfix sözdizimi kullanımı güzel olduğunu düşünüyorum.

(Ben de düz bir uygulamaya çalıştık [ ... ]için tam olarak aynı şekilde dizeleri endekslenmesi için varyantı Positionals ama beni aşan nedenlerle işin bu gece bunu elde etmek için başarısız olmuş Esrarlı. [+ ... ]Exdices yapmak için çalışacağını ancak endekslerini yapmak değil; marka olduğunu Bana hiçbir anlam ifade etmiyor! Her neyse, elimde olanları paylaşacağım ve bu cevabı eksiksiz olarak değerlendireceğim.


[Düzenle: Yukarıdaki çözümün ayrı görülmesi gereken iki yönü vardır. İlk olarak, kullanıcı tanımlı bir operatör postcircumfix:<[- ]> (Str ..., beyan tarafından sağlanan sözdizimsel şeker ,. İkincisi, bu deklarasyonun gövdesi. Yukarıda Brad'in çözümünü (bir varyantını) kullandım. Orijinal cevabım aşağıda.]


Sorunuz, a'nın bazı endekslerini kaldırmak ve sonucu .combyeniden oluşturmak joiniçin kaynadığından , sorunuz aslında ... 'nın bir kopyasıdır .

Dizi veya liste öğelerinin seçimini kaldırmanın hızlı bir yolu nedir? .comb ... .joinburaya [ ] yanıtları için daha fazla çözüm ekliyor .


İki multis olarak uygulanır, böylece aynı sözdizimi Positionals ile kullanılabilir :

multi postcircumfix:<[- ]> (Str $_, *@exdex) { .comb[- @exdex ].join }

multi postcircumfix:<[- ]> (@pos,   *@exdex) { sort keys ^@pos (-) @exdex } 

say '0123456789'[- 1..3, 8 ]; # 045679

say (0..9)[- 1..3, 8 ];       # (0 4 5 6 7 9)

sort keys ^@pos (-) @exdicesUygulama sadece Sebastian'ın cevap @ biraz daha basitleştirilmiş bir versiyonudur. Yukarıda bağladığım önceki cevaptan jnthn'in çözümüne karşı bir kıyaslama yapmadım, ancak daha hızlıysa, bunun yerine değiştirilebilir. [Düzenle: Açıkçası bunun yerine Brad'in dize varyantı için çözümü olmalıdır .


"Bence basit bir postcircumfix sözdizimi kullanmak güzel". Kesinlikle! Bu çözümü seviyorum: okumak için süper net.
Tinmarino

8

yine başka bir varyant:

print $_[1] if $_[0] !(elem) (1,2,3,8) for ^Inf Z 0..9;

.print for ((0..9) (-) (1,2,3,8)).keys;

8

Bu sadelik ve kısalık açısından en yakın olanı.

say '0123456789'.comb[ |(3..6), |(8..*) ].join

7

Herkes, dizeyi combdüz bir indeks listesi kullanarak veya kullanarak bir listeye dönüştürüyor .

Bunlardan herhangi birini yapmak için hiçbir sebep yok

sub remove( Str:D $str is copy, +@indices ){
    for @indices.reverse {
        when Int   { $str.substr-rw($_,1) = '' }
        when Range { $str.substr-rw($_  ) = '' }
    }
}

remove("0123456789",  1..3, 8 );  # 045679
remove("0123456789", [1..3, 8]);  # 045679

Yukarıdaki endekslerin en düşükten en yükseğe doğru olduğunu ve örtüşme olmadığını varsayar.


Bu, makinemdeki 150 faktörünün (ile my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat) en hızlı cevabı . Tarak uzun dizeler için uzun Teşekkürler @BradGilbert, bu kesinlikle en azından bana bazı insanlara yardımcı olacaktır :-)
Tinmarino

1
@Tinmarino MoarVM genellikle dizeleri kopyalamaz, bunun yerine orijinal dizeye işaret eden alt dize nesneleri oluşturur. Kullandığınızda .comb, bu nesnelerin çoğunu oluşturmak ve onları tekrar birleştirmek zorundadır. Bununla substrbirlikte bu nesnelerden mümkün olduğunca azını oluşturur.
Brad Gilbert

"özgün dizeye işaret eden alt dize nesneleri": bu yüzden Str'nin değişmez olarak uygulanmasına karar verildi mi? Yine de etkileyici optimizasyon.
Mart'ta Tinmarino 28:19

5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.