Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to form a new array based on part of an existing array

Tags:

perl

I was trying to build a new array based on an existing array.

#!/usr/bin/perl
#join
use warnings;
use strict;

my @names = ('jacob', 'michael', 'joshua', 'mathew');
my @t_names = join ("\t" , @names);
my @t_names2 = join ("\t", $names[0],$names[2]);
print @t_names, "\n";
print @t_names2, "\n";

The test script allows me to join 2 elements from the old array to form a new array. But what if my array has 1000 elements and I would like to form a new array that contains only a selective portion of the 1000 elements (say, element 3 and 3 multiples). I tried join ("\t", $names[0,2]) but perl doesn't recognize $names[0,2] (output suggests that $names[0,2] is "recognized" as $names[2]. And not sure what this error means "multidimensional syntax not supported at join.pl"

If join is not the right function, what other way could I build a partial array from an existing array? Thank you.

like image 744
B Chen Avatar asked Apr 19 '13 20:04

B Chen


2 Answers

To get a slice of an array, use @names[0,2], not $names[0,2].

To get an explanation of an error message, use diagnostics;, which gives:

Multidimensional syntax $names[0,2] not supported at ...

(W syntax) Multidimensional arrays aren't written like $foo[1,2,3]. They're written like $foo[1][2][3], as in C.

which is perl noticing you are doing something wrong but being wrong about what you were trying to do :)

join creates a string, never a list, so presumably you want to just:

my @new_array = @names[ @indexes_to_select ];

To select only indexes from 3 on that are multiples of 3:

my @new_array = @names[ grep $_ % 3 == 0, 3..$#names ];
like image 165
ysth Avatar answered Nov 14 '22 19:11

ysth


Whenever you want more than one thing out of an array, whether it's all the items or some subset, you use @ instead of $.

You can select any subset of items from an array with @arrayname[list], where list is a list of indexes. You can put a literal list of comma-separated index values, but you can also put any expression that returns a list. ysth's solution uses the expression grep $_ % 3 == 0, 3..$#names. Breaking it down, that uses these elements:

  • $#names to get the index of the last element in @names
  • the range construct .. to generate a list of all the numbers from 3 up to that value
  • grep to extract from that list of numbers only the ones matching a condition
  • that condition being the expression $_ % 3 == 0, which means "the remainder when the number is divided by 3 is 0", which of course is only true for multiples of 3

So if the array has 1000 elements, then $#names is 999, and 3..$#names is a 997-element list containing the numbers (3,4,5,6,7,8,...) all the way up to 999. Running grep $_ % 3 == 0 on that list returns a 333-element list containing the numbers (3,6,9,12,...) all the way up to 999, and then asking for @names[3,6,9,12,...,996,999] returns the 333 elements located at those positions in the @names array.

like image 38
Mark Reed Avatar answered Nov 14 '22 19:11

Mark Reed