Rimuovi alcuni caratteri da una stringa per indice (Raku)


15

FAQ: In Raku, come si rimuovono alcuni caratteri da una stringa, in base al loro indice?

Supponiamo di voler rimuovere gli indici da 1 a 3 e 8

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

Risposte:


14

La variante di Shnipersons risponde:

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

In una riga:

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

o chiamato da una funzione:

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

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

o con aumento di Str:

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

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

A mio avviso, questo risolve completamente il problema. Grazie per aver ricordato che \ e (-) sono equivalenti. Non vedo altri modi per fetta con l'indice I Non voglio e non gli indici che voglio.
Tinmarino,

1
Non devi usarlo MONKET-TYPINGse lo rendi solo un metodo mobile libero e lo chiami come 'foobar'.&remove: (1..2, 4); (aumentando può avere problemi con la composizione se usato più volte)
user0721090601

(il che non vuol dire che l'aumento è negativo, solo che .&removeè un modo per rimuoverlo.
user0721090601

Ho aggiunto la variante non aumentata al tuo suggerimento. Grazie.
Sebastian

1
∖ confuso e sembra un personaggio rovesciato.
Shniperson,

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

9

La mia ultima idea per un'operazione non attiva (tratterò l'implementazione di seguito):

Uso:

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

Implementazione, wrapping (una variante della) Soluzione di Brad:

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

La sintassi per usare l'operatore che ho dichiarato è string[- list-of-indices-to-be-subtracted ], cioè usando una [...]notazione familiare , ma con una stringa a sinistra e un segno meno dopo l'apertura [per indicare che il contenuto del pedice è un elenco di exdices piuttosto che di indici .

[Modifica: ho sostituito la mia implementazione originale con quella di Brad. Probabilmente è sbagliato perché, come osserva Brad, la sua soluzione "presume che gli [exdices] siano in ordine dal più basso al più alto, e non vi siano sovrapposizioni", e mentre il suo non promette diversamente, usare [- ... ]è terribilmente vicino a così facendo. Quindi, se questo zucchero di sintassi dovesse essere usato da qualcuno, probabilmente non dovrebbe usare la soluzione di Brad. Forse c'è un modo per eliminare il presupposto di Brad.]

Mi piace questa sintassi ma sono consapevole del fatto che Larry non è stato deliberatamente utilizzato [...]per indicizzare le stringhe, quindi forse la mia sintassi qui non è appropriata per l'adozione diffusa. Forse sarebbe meglio se fossero usati alcuni caratteri di bracketing diversi. Ma penso che l'uso di una semplice sintassi postcircumfix sia piacevole.

(Ho anche provato a implementare una [ ... ]variante semplice per indicizzare le stringhe esattamente allo stesso modo di Positionals ma non sono riuscito a farlo funzionare per motivi al di là di me stanotte. Stranamente [+ ... ]lavoreremo per fare degli exd ma non per fare gli indici; questo rende non ha alcun senso per me! Ad ogni modo, posterò quello che ho e considero completa questa risposta.)


[Modifica: la soluzione sopra ha due aspetti che dovrebbero essere visti come distinti. Innanzitutto, un operatore definito dall'utente, lo zucchero sintattico fornito dalla postcircumfix:<[- ]> (Str ...dichiarazione. In secondo luogo, il corpo di tale dichiarazione. In quanto sopra ho usato (una variante della) soluzione di Brad. La mia risposta originale è sotto.]


Poiché la tua domanda si riduce alla rimozione di alcuni indici di a .comb, e alla rielaborazione joindel risultato, la tua domanda è essenzialmente un duplicato di ... [Modifica: Sbagliato, secondo la risposta di Brad.]

Qual è un modo rapido per deselezionare gli elementi dell'array o dell'elenco? aggiunge ancora più soluzioni per le [ .comb ... .join] risposte qui.


Implementato come due multis in modo che la stessa sintassi possa essere utilizzata con Positionals:

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)

L' sort keys ^@pos (-) @exdicesimplementazione è solo una versione leggermente semplificata della risposta di @ Sebastian. Non l'ho confrontato con la soluzione di jnthn dalla risposta precedente che ho collegato sopra, ma se è più veloce allora può essere scambiato. * [Modifica: ovviamente dovrebbe essere invece la soluzione di Brad per la variante di stringa.] *


"Penso che l'uso di una semplice sintassi postcircumfix sia piacevole". Decisamente ! Adoro questa soluzione: super chiara da leggere.
Tinmarino,

8

ancora altre varianti:

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

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

8

Questo è il più vicino che ho ottenuto in termini di semplicità e mancanza.

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

7

Ognuno sta trasformando la stringa in un elenco usando combo usando un elenco piatto di indici.

Non c'è motivo di fare nessuna di queste cose

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

Quanto sopra presuppone che gli indici siano in ordine dal più basso al più alto e che non vi siano sovrapposizioni.


Questa è la risposta più veloce di un fattore 150 sulla mia macchina (con my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat). Il pettine è lungo per le corde lunghe Grazie @BradGilbert, questo aiuterà sicuramente alcune persone, almeno io :-)
Tinmarino,

1
@Tinmarino Questo perché MoarVM di solito non copia le stringhe, ma crea oggetti di sottostringa che puntano nella stringa originale. Quando lo usi .combdeve creare molti di quegli oggetti e combinarli di nuovo insieme. Con substresso crea il minor numero possibile di quegli oggetti.
Brad Gilbert,

"sottostringa oggetti che puntano nella stringa originale": è per questo che è stato deciso di implementare Str come immutabile? Ottimizzazione impressionante comunque.
Tinmarino,

5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.