tags:

views:

152

answers:

6

Hi All,

I want to create arrays dynamically based on the user input. e.x.

If user gives input as 3 then 3 arrays should be created with the name @message1 @message2 @message3.

How to do it in perl.

Thanks Senthil kumar.

+10  A: 

I have to ask why you want to do this, because it's not the right way to go. If you have three streams of input, each of which needs to be stored as a list, then store one list, which is a list of the lists (where the lists are stored as array references):

my @input = (
    [ 'data', 'from', 'first', 'user' ],
    [ qw(data from second user) ],
    [ qw(etc etc etc) ],
);

If you have names associated with each user's data, you might want to use that as a hash key, for indexing the data against:

my %input = (
    senthil => [ 'data', 'from', 'first', 'user' ],
    ether => [ qw(data from second user) ],
    apu => [ qw(etc etc etc) ],
);

Please refer to the Perl Data Structures Cookbook (perldoc perldsc) for more on selecting the right data structure for the situation, and how to define them.

Ether
Good answer - except you refer several times to "lists" when you mean "arrays". In Perl, lists and arrays are not the same things. Lists are data, arrays are variables.The difference is subtle, but important.
davorg
@davorg: I meant lists when I said lists. Lists can be stored as *arrays*, or *arrayrefs*, and also in *hashes*.
Ether
+12  A: 

Don't. Instead, use an array of arrays:

my @message;
my $input = 3;
for my $index ( 0..$input-1 ) {
    $message[$index][0] = "element 0";
    $message[$index][1] = 42;
}
print "The second array has ", scalar( @{ $message[1] } ), " elements\n";
print "They are:\n";
for my $index ( 0..$#{ $message[1] } ) {
    print "\t", $message[1][$index], "\n";
}

Some helpful rules are at http://perlmonks.org/?node=References+quick+reference

ysth
A: 

Wow, didn't know Perl didn't have an easy way to do it. Even in Logo it is pretty easy:

repeat readword [make (word "message repcount) array 10]

show :message1
{[] [] [] [] [] [] [] [] [] []}

show :message2
{[] [] [] [] [] [] [] [] [] []}

show :message3
{[] [] [] [] [] [] [] [] [] []}
DanielAjoy
Perl does have an easy way to do it, we're just not telling because it's 99% of the time the wrong thing to do.
ysth
Wasn't me that downvoted. There's a nice series of articles at http://perl.plover.com/varvarname.html
ysth
+1 just to offset the needless beatdown. @DanielAjoy: It's this simple in Perl: `${"message_$_"} = [ ( [] ) x 10 ] foreach 1..$input;`-- the question is *why* do it symbolically, when it's just a simple list of lists.
Axeman
A: 

you can create arrays without knowing their name beforehand.

$second_name='the_second_array';
@$second_name=[1,2,3];

now you have @the_second_array filled with [1,2,3].

Hermann Ingjaldsson
This is a terrible way to code and will make whoever maintains your code hate you.
Oesor
the guy was asking for how to do this, so i told him how to do this
Hermann Ingjaldsson
:) "When people come into comp.lang.perl.misc asking how to do something stupid, I'm never quite sure what to do. I can just answer the question as asked, figuring that it's not my problem to tell people that they're being stupid. That's in my self-interest, because it takes less time to answer the question that way, and because someone might someday pay me to clean up after their stupidity" - mjd, in http://perl.plover.com/varvarname.html
ysth
+2  A: 

In a compiled languages, variables don't have a name. The name you see in the code is a unique identifier associated with some numerical offset. In an identifier like message_2 the '2' only serves to make it a unique identifier. Anybody can tell that you could make your three variables: message_125, message_216, and message_343. As long as you can tell what you should put into what, they work just as well as message_1....

The "name" of the variable is only for you keeping them straight while you're writing the code.

Dynamic languages add capability by not purging the symbol table(s). But a symbol table is simply an association of a name with a value. Because Perl offers you lists and hashes so cheaply, there is no need to use the programming/logistical method of keeping track of variables to allow a flexible runtime access.

Chances are that if you see yourself naming lists @message1, @message2, ... -- where the items differ only by their reference order, that these names are just as good: $message[1], $message[2], ....

In addition, since symbol tables are usually mapping from name-to-offset (either on the stack or in the heap), it's really not a whole lot more than a key-value pair you find in a hash. So hashes work just as good for looking up more distinct names.

$h{messages} = [];
$h{replies}  = [];

I mean really if you wanted to, you could store everything that you put into a lexical variable into a single hash for the scope, if you didn't mind writing: $h{variable_name} for everything. But you wouldn't get the benefit of Perl's implicit scope management, and across languages, programmers have preferred implicit scope management.

Perl allows symbolic manipulation, but over the years the dynamic languages have found that a mixed blessing. But in Perl you have both "perspectives", to give them a name. Because you can determine what code in a compiled language is likely to do better than a dynamic language, it has been determined more error free to use a "compiled perspective" for more things: So as you can see with the availability of offset-management and lookup compiled behavior given to you in core Perl, there is no reason to mess with the symbol table, if you don't have to.

Creating an array dynamically, is as simple as: []. Assigning it to a spot in memory, when we don't know how many we want to store, is as easy as:

push @message, []; 

And creating a list of lists all at once is as easy as:

@message = map { [] } 1..$num_lists;

for some specified value in $num_lists.

Axeman
`([])x` creates multiple copies of the same array reference; you want `map([],1..$num_lists)` instead
ysth
@ysth, ya know, I wrote it first with a map, but thought the multiplier looked faster. :)
Axeman
and so it is :)
ysth
+2  A: 

Creating new named arrays dynamically is almost never a good idea. Mark Dominus, author of the enlightening book Higher-Order Perl, has written a three-part series detailing the pitfalls.

You have names in mind for these arrays, so put them in a hash:

sub create_arrays {
  my($where,$n) = @_;

  for (1 .. $n) {
    $where->{"message$_"} = [];
  }
}

For a quick example that shows the structure, the code below

my $n = @ARGV ? shift : 3;

my %hash;
create_arrays \%hash, $n;

use Data::Dumper;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper \%hash;

outputs

$ ./prog.pl
{
  'message2' => [],
  'message3' => [],
  'message1' => []
}

Specifying a different number of arrays, we get

$ ./prog.pl 7
{
  'message2' => [],
  'message6' => [],
  'message5' => [],
  'message4' => [],
  'message3' => [],
  'message1' => [],
  'message7' => []
}

The order of the keys looks funny because they're inside a hash, an unordered data structure.

Recall that [] creates a reference to a new anonymous array, so, for example, to add values to message2, you'd write

push @{ $hash{"message2"} }, "Hello!";

To print it, you'd write

print $hash{"message2"}[0], "\n";

Maybe instead you want to know how long all the arrays are:

foreach my $i (1 .. $n) {
  print "message$i: ", scalar @{ $hash{"message$i"} }, "\n";
}

For more details on how to use references in Perl, see the following documentation:

Greg Bacon