¿Cómo divido agradable / idiomáticamente una cadena en una lista de posiciones?
Lo que tengo:
.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, * );
}
}
Lo cual es razonable. Sin embargo, estoy desconcertado por la falta de soporte de idiomas para esto. Si "dividir en" es una cosa, ¿por qué no "dividir en" también? Creo que esto debería ser una operación central. Debería poder escribir
.say for "0019ABX26002".split( :at(3, 4, 8) );
¿O tal vez estoy pasando por alto algo?
Editar: un pequeño punto de referencia de lo que tenemos hasta ahora
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")?Respuestas:
Personalmente lo dividiría en una lista, utilizo
rotorpara dividir la lista y unir el resultado:Si desea una división en la función (usando los índices dados):
Básicamente, si quiero hacer cosas de tipo de lista, uso una lista.
Se me ocurrió otra versión que realmente me gusta por un sentido de programación funcional:
Resulta ser un poco más lento que el otro.
fuente
rotor. En este caso, sin embargo. Estás haciendo mucho trabajo para lo que debería ser una operación simple.De una sola mano:
muestra:
fuente
== 3|4|8con el∈ @posde mejorar la velocidad. (Y algunos podrían preferir la forma en que se lee también.)Debido a que cada subcadena no depende de la otra, hiper se convierte en una opción.
O en forma secundaria:
Pero la sobrecarga involucrada no vale la pena a menos que la cantidad de elementos solicitados sea extrema: en mis pruebas es aproximadamente diez veces más lenta que la forma ingenua.
fuente
Aquí está la solución que usaría:
El
gather/takepermite que sea flojo si finalmente no necesita usarlos todos. El bucle toma@i(2,3,4en el ejemplo) y lo cierra con el reductor de adición en cascada[\+], que normalmente produciría2,5,9, pero insertamos un 00,2,5,9para marcar los índices iniciales de cada uno. Esto permite que la toma real sea simplesubstroperación .Al convertirlo
methoden un sub en lugar de un sub, puede usarlo como lo haría (incluso podría nombrarlosplitsi lo desea, la adición de&sigilo significa que Raku no se confundirá si desea el incorporado o personalizado.Incluso podría agregarlo directamente a Str:
En este caso, debe definirse como
multi methodya existen variossplitmétodos. Lo bueno es que, dado que ninguno de esos se define solo porIntargumentos, es fácil asegurarse de que se use nuestro aumentado.Dicho esto, llamarlo usando la versión sigulada en un léxico
methodes definitivamente la mejor.fuente
:atparámetro con nombre, lo actualizaré para hacerlo.split. Tal sería una adición razonable, en mi humilde opinión.comblugar de ensplit, ya que el peine ya está diseñado para trabajar en números enteros. ¿Qué tal esto? tio.run/##VVLJasMwFLz7KwYTgk1dZyn0kODQaw@FQo4lLbIs26LygiTThCy/…