Wie teile ich eine Zeichenfolge an einer Liste von Positionen schön / idiomatisch auf?
Was ich habe:
.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, * );
}
}
das ist vernünftig. Ich bin jedoch verwirrt über den Mangel an Sprachunterstützung dafür. Wenn "Teilen auf" eine Sache ist, warum wird "Teilen auf" nicht auch? Ich denke, dies sollte eine Kernoperation sein. Ich sollte schreiben können
.say for "0019ABX26002".split( :at(3, 4, 8) );
Oder übersehe ich vielleicht etwas?
Edit: Ein kleiner Benchmark von dem, was wir bisher haben
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
Code:
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")
?Antworten:
Persönlich würde ich es in eine Liste
rotor
aufteilen , verwenden , um die Liste aufzuteilen und das Ergebnis zu verbinden:Wenn Sie eine Aufteilung bei Funktion wünschen (unter Verwendung der angegebenen Indizes):
Grundsätzlich verwende ich eine Liste, wenn ich Dinge vom Listentyp machen möchte.
Ich habe mir eine andere Version ausgedacht, die ich aus funktionaler Programmierrichtung wirklich mag:
Es ist etwas langsamer als das andere.
quelle
rotor
. In diesem Fall allerdings. Sie erledigen eine Menge Arbeit für eine einfache Bedienung.Einweg:
zeigt an:
quelle
== 3|4|8
durch ersetzen∈ @pos
, um die Geschwindigkeit zu verbessern. (Und einige mögen es vielleicht auch vorziehen, wie es liest.)Da jeder Teilstring nicht vom anderen abhängt, wird Hyper zu einer Option.
Oder in Unterform:
Der Aufwand lohnt sich jedoch nur, wenn die Anzahl der angeforderten Elemente extrem ist - in meinen Tests ist er etwa zehnmal langsamer als die naive Form.
quelle
Hier ist die Lösung, die ich verwenden würde:
Das
gather
/take
lässt es faul sein, wenn Sie letztendlich nicht alle verwenden müssen. Die Schleife nimmt@i
(2,3,4
im Beispiel) und komprimiert sie mit dem kaskadierenden Additionsreduzierer[\+]
, der normalerweise erzeugt2,5,9
wird. Wir fügen jedoch eine 0 ein, um0,2,5,9
die Startindizes jedes einzelnen zu markieren. Dies ermöglicht eine einfachesubstr
Operation.Wenn Sie es
method
zu einem Sub machen, können Sie es so verwenden, wie Sie es möchten (Sie können es sogar benennen,split
wenn Sie möchten. Das Hinzufügen des&
Siegels bedeutet, dass Raku nicht verwirrt ist, ob Sie das eingebaute oder das speziell angefertigte möchten.Sie können es sogar direkt zu Str hinzufügen:
In diesem Fall muss definiert werden,
multi method
dass es bereits verschiedenesplit
Methoden gibt. Das Schöne ist, da keines davon nur durchInt
Argumente definiert ist , ist es einfach sicherzustellen, dass unser erweitertes verwendet wird.Das heißt, es
method
ist definitiv besser , es mit der Sigiled-Version in einem Lexikon zu bezeichnen.quelle
:at
benannten Parameter bevorzugen . Ich werde dies aktualisieren.split
. Ein solcher wäre eine vernünftige Ergänzung, imho.comb
als insplit
, da comb bereits für die Arbeit mit ganzen Zahlen ausgelegt ist. Wie wäre es damit? tio.run/##VVLJasMwFLz7KwYTgk1dZyn0kODQaw@FQo4lLbIs26LygiTThCy/…