Como faço para dividir uma sequência de caracteres bem / idioma em uma lista de posições?
O que eu tenho:
.say for split-at( "0019ABX26002", (3, 4, 8) );
sub split-at( $s, @positions )
{
my $done = 0;
gather
{
for @positions -> $p
{
take $s.substr($done, $p - $done );
$done = $p;
}
take $s.substr( $done, * );
}
}
o que é razoável. Estou intrigado com a falta de suporte ao idioma para isso. Se "dividir em" é uma coisa, por que não "dividir em" também? Eu acho que isso deve ser uma operação central. Eu deveria ser capaz de escrever
.say for "0019ABX26002".split( :at(3, 4, 8) );
Ou talvez eu esteja negligenciando alguma coisa?
Edit: Um pequeno benchmark do que temos até agora
O------------O---------O------------O--------O-------O-------O
| | Rate | array-push | holli | raiph | simon |
O============O=========O============O========O=======O=======O
| array-push | 15907/s | -- | -59% | -100% | -91% |
| holli | 9858/s | 142% | -- | -100% | -79% |
| raiph | 72.8/s | 50185% | 20720% | -- | 4335% |
| simon | 2901/s | 1034% | 369% | -98% | -- |
O------------O---------O------------O--------O-------O-------O
Código:
use Bench;
my $s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccddddddddddddddddddddddddddddddddddddefggggggggggggggggggg";
my @p = 29, 65, 69, 105, 106, 107;
Bench.new.cmpthese(1000, {
holli => sub { my @ = holli($s, @p); },
simon => sub { my @ = simon($s, @p); },
raiph => sub { my @ = raiph($s, @p); },
array-push => sub { my @ = array-push($s, @p); },
});
#say user($s, @p);
sub simon($str, *@idxs ) {
my @rotors = @idxs.map( { state $l = 0; my $o = $_ - $l; $l = $_; $o } );
$str.comb("").rotor( |@rotors,* ).map(*.join(""));
}
sub raiph($s, @p) {
$s.split( / <?{$/.pos == any(@p)}> / )
}
sub holli( $s, @positions )
{
my $done = 0;
gather
{
for @positions -> $p
{
take $s.substr($done, $p - $done );
$done = $p;
}
take $s.substr( $done, * );
}
}
sub array-push( $s, @positions )
{
my $done = 0;
my @result;
for @positions -> $p
{
@result.push: $s.substr($done, $p - $done );
$done = $p;
}
@result.push: $s.substr( $done, * );
@result;
}
("001", "9", "ABX2", "6002")
:?Respostas:
Pessoalmente, eu o dividiria em uma lista, use
rotor
para dividir a lista e juntar o resultado:Se você deseja uma divisão na função (usando os índices fornecidos):
Basicamente, se eu quiser fazer coisas do tipo lista, eu uso uma lista.
Eu vim com outra versão que eu realmente gosto de um sentido de programação funcional:
Funciona para ser um pouco mais lento que o outro.
fonte
rotor
. Nesse caso, porém. Você está trabalhando muito para o que deveria ser uma operação simples.Mão única:
exibe:
fonte
== 3|4|8
por∈ @pos
para melhorar a velocidade. (E alguns podem preferir a forma como se lê também.)Como cada substring não depende do outro, hyper se torna uma opção.
Ou na forma secundária:
Mas a sobrecarga envolvida não vale a pena, a menos que o número de elementos solicitados seja extremo - nos meus testes é cerca de dez vezes mais lento que a forma ingênua.
fonte
Aqui está a solução que eu usaria:
O
gather
/take
permite que seja preguiçoso se você não precisar usar todos eles. O loop pega@i
(2,3,4
no exemplo) e o fecha com o redutor de adição em cascata[\+]
, que normalmente produziria2,5,9
, mas inserimos um 00,2,5,9
para marcar os índices iniciais de cada um. Isso permite que a tomada real seja umasubstr
operação simples .Ao torná-lo um em
method
vez de um sub, você pode usá-lo como faria (você pode até nomeá-lo,split
se quiser, a adição do&
sigil significa que Raku não ficará confuso se você deseja o embutido ou personalizado.Você pode, inclusive, adicioná-lo diretamente ao Str:
Nesse caso, ele precisa ser definido, pois
multi method
já existem váriossplit
métodos. O bom é que, como nenhum deles é definido apenas porInt
argumentos, é fácil garantir que o nosso aumentado seja usado.Dito isto, chamá-lo usando a versão sigilada em um léxico
method
é definitivamente o melhor.fonte
:at
parâmetro nomeado, atualizarei para fazer isso.split
. Tal seria uma adição razoável, imho.comb
do que emsplit
, pois o pente já foi projetado para funcionar com números inteiros. Que tal agora? tio.run/##VVLJasMwFLz7KwYTgk1dZyn0kODQaw@FQo4lLbIs26LygiTThCy/…