Remova alguns caracteres de uma string pelo índice (Raku)

15

FAQ: No Raku, como você remove alguns caracteres de uma string, com base em seu índice?

Digamos que eu queira remover os índices 1 a 3 e 8

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

Respostas:

14

Variante da resposta de Shniperson:

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

Em uma linha:

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

ou chamado por uma função:

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

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

ou com aumento de Str:

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

say '0123456789'.remove: (1..3, 8);
Sebastian
fonte
Isso resolve o problema completamente na minha opinião. Obrigado por lembrar que \ e (-) são equivalentes. Não vejo outras maneiras de cortar com o índice que não quero e não com os índices que quero.
Tinmarino 26/03
11
Você não precisa usar o MONKET-TYPINGmétodo flutuante gratuito e chamá-lo como 'foobar'.&remove: (1..2, 4); (o aumento pode ter problemas com a composição, se usado várias vezes)
user0721090601
(o que não significa que o aumento seja ruim, apenas que essa .&removeé uma maneira de removê-lo.)
user0721090601 26/03
Eu adicionei a variante sem aumento como sua sugestão. Obrigado.
Sebastian
11
∖ confuso e parece um personagem de barra invertida.
Shniperson 28/03
12
.value.print if .key  !(elem) (1,2,3,8) for '0123456789'.comb.pairs
chenyf
fonte
9

Minha última idéia para uma operação que não está no momento (abordarei a implementação abaixo):

Uso:

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

Implementação, encapsulamento (uma variante) da solução de 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

A sintaxe para usar o operador que declarei é string[- list-of-indices-to-be-subtracted ], ou seja, usando [...]notação familiar , mas com uma sequência à esquerda e um sinal[ de menos adicional após a abertura para indicar que o conteúdo subscrito é uma lista de exdices em vez de índices .

[Editar: Substituí minha implementação original pela de Brad. Provavelmente isso está errado, porque, como observa Brad, sua solução "assume que os [exdices] estão na ordem do mais baixo para o mais alto, e não há sobreposição", e, embora ele não prometa o contrário, o uso [- ... ]é muito próximo de fazendo isso. Portanto, se esse açúcar de sintaxe fosse usado por alguém, ele provavelmente não deveria usar a solução de Brad. Talvez haja uma maneira de eliminar a suposição de Brad.]

Eu gosto desta sintaxe, mas estou ciente de que Larry deliberadamente se não construir no uso de [...]para cadeias índice então talvez o meu sintaxe aqui é inapropriado para adopção generalizada. Talvez seja melhor se alguns caracteres de bracketing diferentes forem usados. Mas acho que o uso de uma simples sintaxe postcircumfix é bom.

(Eu também tentei implementar uma [ ... ]variante direta para indexar strings da mesma maneira que para Positionals, mas não consegui fazê-lo funcionar por razões além de mim hoje à noite. Estranhamente [+ ... ], trabalhará para executar exdices, mas não para índices; isso faz com que não faz sentido para mim! De qualquer forma, vou postar o que tenho e considerar esta resposta completa.)


[Editar: A solução acima tem dois aspectos que devem ser vistos como distintos. Primeiro, um operador definido pelo usuário, o açúcar sintático fornecido pela postcircumfix:<[- ]> (Str ...declaração Segundo, o corpo dessa declaração. No exemplo acima, usei (uma variante da) solução de Brad. Minha resposta original está abaixo.]


Como sua pergunta se resume a remover alguns índices de a .combe obter joino resultado, sua pergunta é essencialmente uma duplicata de ... [Editar: Errado, de acordo com a resposta de Brad.]

Qual é uma maneira rápida de desmarcar matriz ou listar elementos? adiciona ainda mais soluções para as [ .comb ... .join] respostas aqui.


Implementado como dois multis, para que a mesma sintaxe possa ser usada com 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)

A sort keys ^@pos (-) @exdicesimplementação é apenas uma versão ligeiramente simplificada da resposta de @ Sebastian. Eu não o comparei com a solução do jnthn da resposta anterior que eu vinculei acima, mas se for mais rápido, pode ser trocado. * [Edit: Obviamente, deveria ser a solução de Brad para a variante de string.] *

raiph
fonte
"Eu acho que o uso de uma simples sintaxe postcircumfix é legal". Definitivamente ! Adoro esta solução: super clara de ler.
Tinmarino 27/03
8

ainda outras variantes:

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

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

Este é o mais próximo que cheguei em termos de simplicidade e falta de tempo.

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

Todo mundo está transformando a string em uma lista usando combou usando uma lista simples de índices.

Não há razão para fazer uma dessas coisas

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

O exposto acima pressupõe que os índices estão na ordem do menor para o maior e não há sobreposição.

Brad Gilbert
fonte
Esta é a resposta mais rápida por um fator de 150 na minha máquina (com my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat). Pente é longo para longas cordas Obrigado @BradGilbert, isso definitivamente ajudará algumas pessoas, pelo menos eu :-)
Tinmarino
11
@Tinmarino Isso ocorre porque o MoarVM geralmente não copia seqüências de caracteres, mas cria objetos de substring que apontam para a sequência original. Quando você o usa, .combele deve criar muitos desses objetos e combiná-los novamente. Com substrisso, cria o menor número possível de objetos.
Brad Gilbert
"objetos de substring que apontam para a string original": é por isso que foi decidido implementar Str como imutável? Otimização impressionante de qualquer maneira.
Tinmarino 28/03
5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Sebastian
fonte