beginner array of array

G

Guy

I have a 20KB txt file of data that looks something like this: lines of
tab-separated fields.
001 jan2009 house
002 jan2008 barn
003 jun2007 trees
004 mar2006 garden
005 apr2003 lake
006 jul2001 mountain

I'd like to load the entire file in an array and be able to refer to
specific fields in specific records, such as the 1st field of the 4th item.
I tried this but it obviously doesn't work. Can anyone show me the trouble?
It would be much appreciated.
Guy


#!/usr/bin/perl

my $pfil="photos.txt";
my @records;
my $data = \@records;
my $total;

if (open(FIL, $pfil))
{
$total=0;
while (<FIL>)
{
$records[$total] = split(/\t/);
$total++;
}
close FIL;
}

print "$data->[3][0] \n";
 
T

Tad J McClellan

Guy said:
I have a 20KB txt file of data that looks something like this: lines of
tab-separated fields.
001 jan2009 house
002 jan2008 barn
003 jun2007 trees
004 mar2006 garden
005 apr2003 lake
006 jul2001 mountain


Those are not tab separated.

Those are space separated.

I'd like to load the entire file in an array and be able to refer to
specific fields in specific records, such as the 1st field of the 4th item.
#!/usr/bin/perl


use warnings;
use strict;

my $data = \@records;


You do not need any references at that level.


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

my @records;
while ( <DATA> ) {
chomp;
push @records, [ split ];
}

print $records[3][0], "\n";

__DATA__
001 jan2009 house
002 jan2008 barn
003 jun2007 trees
004 mar2006 garden
005 apr2003 lake
006 jul2001 mountain
 
J

Jürgen Exner

Guy said:
I have a 20KB txt file of data that looks something like this: lines of
tab-separated fields.
001 jan2009 house
002 jan2008 barn
003 jun2007 trees
004 mar2006 garden
005 apr2003 lake
006 jul2001 mountain

I'd like to load the entire file in an array and be able to refer to
specific fields in specific records, such as the 1st field of the 4th item.
I tried this but it obviously doesn't work. Can anyone show me the trouble?

You are storing the split() result in an array element. Array elements
are scalars, therefore all you get is the scalar value of that split()
result which is the number of elements in that result (that's where the
'3' is coming from in the error message).

Instead you need to create an (anonymous) array with those results.
It would be much appreciated.

use warnings; use strict;

my $pfil="photos.txt";
my @records;
# my $data = \@records; # you dont' need this reference
my $total;

if (open(FIL, '<', $pfil)){
# better to use 3-arg form of open
# you also might want to add a meaningful error message
# $total=0; # not needed, see below
while (<FIL>){
# $records[$total] = split(/\t/);
# $total++;
# use push(), then you don't need to bother with that index $total
push @records, [split(/\t/)];
# creates an anonymous array and pushes ref to it into @records
}
close FIL;
}

$total = @records; #scalar value of an array is its length
print "$records[3][1] \n";
 
G

Guy

You are storing the split() result in an array element. Array elements
are scalars, therefore all you get is the scalar value of that split()
result which is the number of elements in that result (that's where the
'3' is coming from in the error message).

Instead you need to create an (anonymous) array with those results.

use warnings; use strict;

my $pfil="photos.txt";
my @records;
# my $data = \@records; # you dont' need this reference
my $total;

if (open(FIL, '<', $pfil)){
# better to use 3-arg form of open
# you also might want to add a meaningful error message
# $total=0; # not needed, see below
while (<FIL>){
# $records[$total] = split(/\t/);
# $total++;
# use push(), then you don't need to bother with that index $total
push @records, [split(/\t/)];
# creates an anonymous array and pushes ref to it into @records
}
close FIL;
}

$total = @records; #scalar value of an array is its length
print "$records[3][1] \n";

Thank you all sincerely.
I didn't know that push would push the reference of the split's anonymous
array. I thought that push would add the new fields of the split at the end
of @records, creating a long array like:
001 jan2009 house 002 jan2008 barn...

Also, I appreciate the hash advise. It would probably make the script easier
to understand, in the future at least. But it's really a small script, I'm
not sure if it would be necessary, but I'll keep that in mind??

You're correct that those were spaces and not tabs, they must have gotten
converted when I cut & pasted the data.

Guy
 
J

Jürgen Exner

Guy said:
I didn't know that push would push the reference of the split's anonymous
array. I thought that push would add the new fields of the split at the end
of @records, creating a long array like:
001 jan2009 house 002 jan2008 barn...

It would, if you'd use it like
push @records, split(/\t/);

That's why you have to create the anonymous array using
push @records, [split(/\t/)];

jue
 
U

Uri Guttman

G> I didn't know that push would push the reference of the split's
G> anonymous array. I thought that push would add the new fields of
G> the split at the end of @records, creating a long array like:

split doesn't have an anonymous array. be clear in what you are saying
or asking. these records are made from splitting a line by spaces and
putting those fields into an anon array. THAT array reference (which has nothing
to do with split but holds its results) is pushed (as a single scalar
value) onto the @records array.


G> Also, I appreciate the hash advise. It would probably make the
G> script easier to understand, in the future at least. But it's
G> really a small script, I'm not sure if it would be necessary, but
G> I'll keep that in mind??

you should learn it now. indexing fields by number and not name is prone
to bugs and misunderstanding later. this will bite you one day for sure
so learn hashes now.

uri
 
T

Ted Zlatanov

UG> you should learn it now. indexing fields by number and not name is prone
UG> to bugs and misunderstanding later. this will bite you one day for sure
UG> so learn hashes now.

Arrays use less memory, which can become important for some
applications. If I face that situation, I usually use constants to
reduce the chance of error:

use constant NAME => 0;
use constant SURNAME => 1;

my @data;
$data[NAME] = 'John';

Obviously Uri's advice is valid too, it's just that in some cases you
are forced to use arrays.

Ted
 
U

Uri Guttman

UG> you should learn it now. indexing fields by number and not name is prone
UG> to bugs and misunderstanding later. this will bite you one day for sure
UG> so learn hashes now.

TZ> Arrays use less memory, which can become important for some
TZ> applications. If I face that situation, I usually use constants to
TZ> reduce the chance of error:

TZ> use constant NAME => 0;
TZ> use constant SURNAME => 1;

and that will bite you even harder when you need to add/delete/change
keys. trust me, i have seen it. if you want proof, look at the modules
which give ordering to hashes. all have major fails when things change.

if you are ram sensitive, usually you can find other ways to save space
other than using arrays over hashes.

TZ> Obviously Uri's advice is valid too, it's just that in some cases you
TZ> are forced to use arrays.

for some definition of forced! :)

uri
 
T

Ted Zlatanov

UG> you should learn it now. indexing fields by number and not name is prone
UG> to bugs and misunderstanding later. this will bite you one day for sure
UG> so learn hashes now.

TZ> Arrays use less memory, which can become important for some
TZ> applications. If I face that situation, I usually use constants to
TZ> reduce the chance of error:

TZ> use constant NAME => 0;
TZ> use constant SURNAME => 1;

UG> and that will bite you even harder when you need to add/delete/change
UG> keys. trust me, i have seen it. if you want proof, look at the modules
UG> which give ordering to hashes. all have major fails when things change.

Assuming you need to modify the key order, yes, this is a bad idea. But
there are many cases where the key order does not need to be modified.
For example, do you expect the TCP packet fields to get reordered often?
getpwent() fields?

UG> if you are ram sensitive, usually you can find other ways to save space
UG> other than using arrays over hashes.

Perhaps, this really depends on the problem. Let's not forget array
lookups are significantly faster than hash lookups. I would rather
evaluate on a case-by-case basis than make a overly general statement.

Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top