2013-03-01 4 views
5

Ho un riferimento a un grande array, e alcuni degli elementi (da qualche indice fino alla fine) devono essere usati per inserire nuove righe in un DB.Perl: taglia un array, senza creare un intero nuovo array

Esiste comunque la possibilità di creare un riferimento a una parte di un array più grande? In alternativa, posso utilizzare una parte di un array con la funzione execute_array di DBI, senza che Perl copi molti dati in background?

Ecco cosa voglio fare in modo più efficiente:

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

(oh vedo, gli argomenti sono una lista di "colonne", dove ogni colonna è un riferimento a una matrice di valori per quella colonna.) – ikegami

+3

Sembra che il tuo Black Mage attacca il mio pollo. ummm ... pollo fritto ... – ikegami

+0

Mi stavo chiedendo. Non posso semplicemente fare qualcosa del tipo: '$ arrayref + = $ index; $ sh-> execute_array ({}, $ arrayref); ' So che questo codice esatto non funzionerà come perl non è C, ma ciò non significa che non possa realizzare la stessa cosa. – Jonathon

risposta

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

è simile a

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

nota l'assegnazione che copia tutti gli elementi della fetta. Siamo in grado di evitare di copiare gli scalari come segue:

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

Ora, stiamo semplicemente copiando puntatori (SV*) invece di intere scalari (e qualsiasi stringa in esso).

+0

Quindi questo dovrebbe funzionare. E facendo alcuni test il riferimento restituito a un array è per gli stessi elementi nel primo array (è possibile modificarli entrambi modificando un elemento in uno di essi). – Jonathon

+0

Leggermente più elegante, se lo fai solo una volta: 'sub {\ @_;} -> (@ {$ arrayref} [2..4]);' – Jonathon

+1

Più compatto, forse, ma non l'ho fatto di proposito usa quello, per 1) non ha le proprietà di auto-documentazione di ciò che ho usato, 2) più difficile da leggere in una situazione di insegnamento, 3) 'sub {my @a = @_; \ @a} -> (...) 'sarebbe stato ancora meno facile da leggere, e 4) ho pensato che lo avresti usato in più di un posto. PS, che ';' è inutile. – ikegami

1

parametro che passa in Perl inizia come 'passaggio dal riferimento'. Se vuoi sapere se è stata eseguita una copia del valore, guarda il codice sorgente.

In questo caso, la definizione di copie di seconda linea execute_array s' i valori di riferimento tramite @_ in una lessicale chiamato @array_of_arrays.

Sul lato positivo, è una copia poco profonda. (Almeno per quanto ho guardato.)

5

fette di array restituire più valori e hanno il sigillo @:

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" 

Una fetta restituirà un elenco (= una serie!) Di scalari. Tuttavia, questa non è una copia in sé:

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

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

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

Quindi questo è abbastanza efficiente.

Se si desidera creare un nuovo array (o un riferimento ad array), è necessario copiare i valori:

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

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

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

La sintassi \@array[1..2] restituirà un elenco di riferimenti a ciascun elemento nella fetta, ma non un riferimento a la fetta.