2013-03-01 10 views
5

Ich habe einen Verweis auf ein großes Array, und einige der Elemente (von einem Index bis zum Ende) müssen verwendet werden, um neue Zeilen in einem DB einzufügen.Perl: Slice ein Array, ohne ein ganz neues Array zu erstellen

Gibt es trotzdem ich kann einen Verweis auf einen Teil eines größeren Array erstellen? Oder kann ich einen Teil eines Arrays mit der Funktion execute_array von DBI verwenden, ohne dass Perl Daten im Hintergrund kopiert?

Hier ist, was ich will, effizienter tun:

$sh->execute_array({}, [ @{$arrayref}[@indexes] ]); 
+0

(oh ich sehe, die Argumente sind eine Liste von "Spalten", wobei jede Spalte ein Verweis auf ein Array von Werten für diese Spalte ist.) – ikegami

+3

Sieht aus wie Ihr Black Mage mein Huhn angreifen. ummm ... gebratenes Huhn ... – ikegami

+0

Ich habe mich gefragt. Könnte ich nicht einfach etwas tun wie: '$ arrayref + = $ index; $ sh-> execute_array ({}, $ arrayref); ' Ich weiß, dass dieser genaue Code nicht funktionieren wird, weil Perl nicht C ist, aber das bedeutet nicht, dass ich nicht dasselbe erreichen kann. – Jonathon

Antwort

4
$sh->execute_array({}, [ @{$arrayref}[@indexes] ]); 

ähnelt

sub new_array { my @a = @_; \@a } 
$sh->execute_array({}, new_array(@{$arrayref}[@indexes])); 

Hinweis der Zuordnung, welche Kopien alle Elemente der Scheibe. Wir können das Kopieren der Skalare vermeiden wie folgt:

sub array_of_aliases { \@_ } 
$sh->execute_array({}, array_of_aliases(@{$arrayref}[@indexes])); 

Jetzt sind wir nur das Kopieren von Zeigern (SV*) anstelle ganzer Skalare (und beliebige Zeichenfolge darin).

+0

Das sollte also funktionieren. Und einige Tests der zurückgegebene Verweis auf ein Array ist für die gleichen Elemente im ersten Array (Sie können beide durch Ändern eines Elements in einem von ihnen ändern). – Jonathon

+0

Etwas eleganter, wenn Sie das nur einmal machen: 'sub {\ @_;} -> (@ {$ arrayref} [2..4]);' – Jonathon

+1

Kompakter, vielleicht, aber ich habe absichtlich nicht benutze das, denn 1) es fehlen die selbstdokumentierenden Eigenschaften dessen, was ich benutzt habe, 2) schwerer in einer Unterrichtssituation zu lesen, 3) 'sub {my @a = @_; \ @a} -> (...) 'wäre noch weniger leicht zu lesen gewesen, und 4) Ich dachte, du würdest es an mehr als einer Stelle benutzen. PS, das ';' ist nutzlos. – ikegami

1

Parameterübergabe in Perl beginnt als 'pass by reference'. Wenn Sie wissen möchten, ob eine Wertkopie erstellt wurde, sehen Sie sich den Quellcode an.

In diesem Fall kopiert die Definition der zweiten Zeile von execute_array die von @_ referenzierten Werte in ein lexikalisches namens @array_of_arrays.

Auf der hellen Seite ist es eine flache Kopie. (Zumindest soweit ich geschaut haben.)

5

Array Scheiben zurückzukehren mehrere Werte und haben die @ Sigil:

my @array = (1, 2, 3, 4); 

print join " ", @array[1..2]; # "2 3" 

my $aref = [1, 2, 3, 4]; 

print join " ", @{$aref}[1..3]; # "2 3 4" 

Eine Scheibe wird eine Liste zurück (= ein Array!) Von Skalare. Dies ist jedoch nicht eine Kopie per se:

my @array = (1, 2, 3, 4); 

for (@array[1..2]) { 
    s/\d/_/; # change the element of the array slice 
} 

print "@array"; # "1 _ _ 4" 

Also das sehr effizient ist.

Wenn Sie ein neues Array (oder ein Array-Referenz) erstellen möchten, müssen Sie die Werte kopieren:

my @array = (1, 2, 3, 4); 

my @slice = @array[1..2]; 

my $slice = [ @array[1..2] ]; 

Die Syntax \@array[1..2] würde eine Liste von Verweisen auf jedes Element in der Scheibe zurück, aber keine Referenz bis die Scheibe.

Verwandte Themen