Nehmen Sie zum Beispiel die hier dargestellte aufeinanderfolgende Sequenz als Array:
my @seq = my $a=0, {++$a} ... *;
for @seq[^10].kv {state $f=0; ($^k < 4 or $^k > 7) ?? say "a$^k = " ~ $^v !! (say "..." if $f ne 1; $f=1) };
Drucke:
a0 = 0
a1 = 1
a2 = 2
...
a8 = 8
a9 = 9
Meine Fragen: 1- Gibt es eine einfache Möglichkeit, nur das erste Element, dh a0 = 0
aus der gedruckten Ausgabe, zu löschen?
2- Könnte dieser Code idiomatischer gemacht werden?
Vielen Dank.
Antworten:
Eine Barebone-Lösung
Beginnen wir mit einer sehr einfachen Lösung zum Drucken eines Kerns einer Sequenz. Es geht nicht um die Details, die Sie Ihrer Frage hinzugefügt haben, aber es ist ein guter Ausgangspunkt:
Im Gegensatz dazu
.kv
, das seinen Invokanten in die Form konvertiertkey1, value1, key2, value2, key3, value3, ...
, dh 6 Elemente, wenn sein Invokant 3 Elemente enthält,.pairs
seinen Invokanten in das Formularkey1 => value1, key2 => value2, key3 => value3, ...
.Ich habe
.pairs
statt.kv
teilweise verwendet, weil es bedeutete, dass ich».gist
später im Code mühelos eine schönekey1 => value1
Anzeige für jedes Element erhalten konnte. Wir werden das unten ändern, aber dies ist ein guter idiomatischer Start.Die
.head
und.tail
-Aufrufe sind die idiomatische Methode, um kleine Listen der ersten und letzten N Elemente aus einer Invocant-Liste zu erstellen (vorausgesetzt, es ist nicht faul; mehr dazu in einem Mo).In Anbetracht dieser anfänglichen Lösung werden
say seq-range-gist (0,1 ... Inf)[^10]
Folgendes angezeigt:Als nächstes möchten wir in der Lage sein, "nur das erste Element ... aus der gedruckten Ausgabe zu löschen". Leider
say seq-range-gist (0,1 ... Inf)[1..9]
zeigt:Wir möchten, dass die Nummer links von der
=>
die Nummerierung der ursprünglichen Sequenz beibehält. Um dies zu ermöglichen, teilen wir die zugrunde liegende Sequenz aus dem Bereich auf, den wir extrahieren möchten. Wir fügen einen zweiten Parameter / ein zweites Argument hinzu@range
und hängen[@range]
an die zweite Zeile des Unterabschnitts an:Jetzt können wir schreiben,
say seq-range-gist (0,1 ... Inf), 1..9
um anzuzeigen:In Ihrer Frage haben Sie
aINDEX = VALUE
eher das Format als verwendetINDEX => VALUE
. Um die Anpassung des Kerns zu ermöglichen, fügen wir einen dritten&gist
Routineparameter / Argument hinzu und rufen diesen anstelle der integrierten.gist
Methode auf:Beachten Sie, wie die "Methoden" -Aufrufe im Hauptteil von
seq-range-gist
sub jetzt.&gist
nicht mehr sind.gist
. Die Syntax.&foo
ruft ein Sub auf&foo
(das normalerweise durchfoo
einfaches Schreiben aufgerufen wird ) und übergibt den Invokanten links von.
als$_
Argument an das Sub.Beachten Sie auch, dass ich den
&gist
Parameter benannt habe, indem ich ihm ein vorangestellt habe:
.So
say seq-range-gist (0,1 ... Inf), 1..9, gist => { "a{.key} = {.value}" }
zeigt nun :Politur hinzufügen
Der Rest dieser Antwort ist Bonusmaterial für Leser, die sich für Politur interessieren.
say seq-range-gist (0, 1, 2, 3), ^3
zeigt an:Hoppla. Und selbst wenn es mehr Paare als Kopf und Schwanz zusammen gäbe, so dass wir zumindest keine wiederholten Linien bekamen, wäre es immer noch sinnlos,
head, ..., tail
nur ein oder zwei Elemente zu entfernen. Lassen Sie uns die letzte Anweisung im Unterkörper ändern, um diese Probleme zu beseitigen:Als nächstes wäre es schön, wenn das U-Boot etwas Nützliches tun würde, wenn es ohne Reichweite oder Kern aufgerufen würde. Wir können das meistens beheben, indem wir den
@range
und&gist
Parametern geeignete Standardeinstellungen geben:Wenn
@seq
es nicht faul ist , wird@range
standardmäßig der gesamte Bereich von verwendet@seq
. Wenn@seq
es unendlich ist (in diesem Fall ist es auch faul), ist die Standardeinstellung von bis zu 100 in Ordnung. Aber was ist, wenn@seq
es faul ist, aber weniger als 100 definierte Werte liefert? Um diesen Fall abzudecken, fügen wir.grep: *.value.defined
der@pairs
Erklärung bei:Eine weitere einfache Verbesserung wären optionale Kopf- und Schwanzparameter, die zu einer endgültigen polierten Lösung führen:
quelle
...
Teil zu rechnen, der eher wie ein C-Programm aussieht. Das beantwortet also wirklich beide Teile meiner Frage. Die "umfassende" Lösung sieht wirklich ein bisschen einschüchternd aus.Sie können die ersten N Werte auf einem
Iterable
oderSequence
mit überspringenskip
:Wenn Sie keine Nummer angeben, wird nur ein Element übersprungen.
quelle
skip
scheint nur die Ausgabe zu entfernen, dh das Element mit dem 0. Index (a0) bleibt übrig. Ich habe es versucht@seq:delete
und es hat gerade das 0. Element durch(Any)
skip
wird nur so tun, als ob die übersprungenen Elemente nicht existieren. Dies kann oder kann nicht sein, was Sie wollen :-)skip
dazwischen setze, so dass es lautet:for @seq[^10].skip(0).kv
Es überspringt buchstäblich nicht das 0. Element und es spielt keine Rolle, ob ichskip
1 oder 2 als Argument gebe , es verzerrt nur das Out weiter. Ich brauche einen praktischen Weg, um das 0. Element von Grund auf zu entfernen.for @seq[^10].kv.skip(2)
ist das, wonach Sie suchen?skip
nach dem zu setzen,.kv
aber andere Argumente als 2 verwendet, also hat es nicht funktioniert. Vielen Dank für die Lösung.Dies könnte etwas idiomatischer sein:
Sie müssen keine lexikalische Variable innerhalb der Sequenz verwenden. Entweder
Whatever
oder Platzhaltervariablen können sicher in Sequenzen verwendet werden. Anschließend können Sie einfach die Elemente der Sequenz auswählen, die gedruckt werden soll. Welches kehrt zurück«(0 1 2 3)(7 8 9 10)»
quelle
whatever
Bediener erfrischt, aber die Serien- / Sequenzausgabe behebt das Hauptproblem nicht. Ich möchte die Serie so drucken, wie sie in Mathe-Texbüchern zu sehen ist, dh mit...
Notation dazwischen.