Jonathon
Jonathon

Reputation: 2699

Perl: Slice an array, without creating a whole new array

I have a reference to an big array, and some of the elements (from some index to the end) need to get used to insert new rows in a DB.

Is there anyway I can create a reference to part of a bigger array? Or another way I can use a part of a array with DBI's execute_array function, without having Perl copy loads of data in the background?

Here's what I want to do more efficiently:

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

Upvotes: 6

Views: 4166

Answers (3)

ikegami
ikegami

Reputation: 385754

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

is similar to

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

Note the assignment which copies all the elements of the slice. We can avoid copying the scalars as follows:

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

Now, we're just copying pointers (SV*) instead of entire scalars (and any string therein).

Upvotes: 4

amon
amon

Reputation: 57600

Array slices return multiple values and have the @ 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"

A slice will return a list (!= an array) of scalars. However, this is not a copy 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"

So this is quite efficient.

If you want to create a new array (or an array reference), you have to copy the values:

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

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

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

The syntax \@array[1..2] would return a list of references to each element in the slice, but not a reference to the slice.

Upvotes: 6

tjd
tjd

Reputation: 4104

Parameter passing in Perl starts out as 'pass by reference'. If you want to know if a value copy is made, look to the source code.

In this case, the definition of execute_array's second line copies the values referenced by @_ into a lexical named @array_of_arrays.

On the bright side, it's a shallow copy. (at least as far as I've looked.)

Upvotes: 1

Related Questions