2013-01-09 19 views
6

Wenn ich nur den 4. extrahieren möchten, 5. und 7. Elemente (sagen wir) von Tab-getrennte Aufzeichnung, kann ich so etwas wie:Wie spezifiziert man eine "Schwanzscheibe" in Perl?

my @f = (split(/\t/, $_, -1))[3, 4, 6]; 

Aber was, wenn ich das vierte Element und das „Schwanz wollen Slice "bestehend aus allen Elementen vom 7. bis zum Ende des Arrays? Ich weiß nicht, wie ich das in einer einzigen Zeile machen soll. Das Beste, was ich tun kann, ist dies:

my @f = split(/\t/, $_, -1); 
@f = @f[3, 6..$#f]; 

Der einzige Grund, dies zu tun Betrieb in zwei Linien ist so, dass ich $#f in der zweiten Zeile angeben kann, aber dies erfordert ein höheres Maß an Spezifität als in der inhärent ist Aufgabe; die Aufgabe nicht wirklich Pflege wie viele Elemente sind in dem Wert von split zurückgegeben. Es wäre schön, in der Lage zu sein, etwas wie "alles ab dem 7. Element verfügbar" zu spezifizieren ... Das ist was ich mit einem "Schwanzstück" meine: ein Stück, wo nur der Startpunkt angegeben wird, während der Endpunkt wird implizit gelassen.

(Diese Art der Spezifikation ist in Verwendungen des cut Dienstprogramm in Unix alltäglich, zB:

... | cut -f 4,7- 

)

Gibt es eine Subskribierung Ausdruck, dass ich direkt an die (split(...)) subexpression bewerben in einer Zeile den gleichen Effekt zu erzielen, wie er durch die letzten beiden obigen Codezeilen erreicht wird?

EDIT: Um klar zu sein, was ich versuche zu vermeiden, ist die $#ARRAY Konstruktion. Ich weiß, dass ich immer so etwas wie

my @f = do { my @t = split(/\t/, $_, -1); @t[3, 6..$#t] }; 

Antwort

8

Der Ausdruck in den Klammern einer Liste Scheibe tun kann, muss eine Liste von Null oder mehreren Indizes zurück. Sie müssen also die Anzahl der Elemente in der Liste wissen, die geschnitten wird, bevor sie überhaupt produziert wird. Also nein, es kann nicht mit einem Listen-Slice gemacht werden.

Der direkteste Zugriff auf eine Liste im Stapel erfolgt über @_. Dies erfordert einen Unteraufruf, aber es gibt Ihnen einen einfachen Mechanismus zum Verlassen der Liste auf dem Stapel.

my @f = sub { @_[6..$#_] }->(split(/\t/, $_, -1)); 

Beachten Sie, dass diese Lösung nicht ein Array schafft und die Werte in diesem Array wie der Code kopieren in die Sie Ihre Frage, da hinzugefügt haben.

+0

erweiterte meine Antwort. – ikegami

+0

sehr cooler Gedanke –

+1

Niiiiiice. Ich mag die Verwendung von '@ _', um einige temporäre Kopien dort zu vermeiden. – LeoNerd

Verwandte Themen