Array dereferencing

J

Jan Fure

Hi;

I the code below, I am creating a data structure of array references.
I want to loop through the keys, and for each key, which corresponds
to multiple values, I want to dereference the data to get a plain
array containing the values. I have read 'perlref', but it is still
not clear to me.

I made the code based on the 'Hashes with Multiple Values Per Key'
from the Perl Coocbook, and also inspired by some posts to this group.

I used Data::Dumper to see that I have the right data.

my %data;
for $row ( @DATA2 ){ #@DATA2 is an array of arrays
push @{ $data{$$row[0]} }, $$row[1];
}
my @points;
foreach ( sort { $a <=> $b } keys %data ) {
@{$data{$_}} = sort { $a <=> $b } @{$data{$_}};
push @{$points[0]}, $_;
push @{$points[1]}, $data{$_};
}
 
J

Jay Tilton

(e-mail address removed) (Jan Fure) wrote:

: I the code below, I am creating a data structure of array references.
: I want to loop through the keys, and for each key, which corresponds
: to multiple values, I want to dereference the data to get a plain
: array containing the values. I have read 'perlref', but it is still
: not clear to me.

Could you phrase that in the form of a question? It's not clear what
you are misunderstanding.

: my %data;
: for $row ( @DATA2 ){ #@DATA2 is an array of arrays
: push @{ $data{$$row[0]} }, $$row[1];
: }
: my @points;
: foreach ( sort { $a <=> $b } keys %data ) {
: @{$data{$_}} = sort { $a <=> $b } @{$data{$_}};
^^^^^^^^^^^^ ^^^^^^^^^^^^
$_ is a hash key.

$data{$_} is the hash value for that key. That value is an array
reference.

@{ $data{$_} } is the referenced array.

Looks like you figured it out pretty well on your own.

: push @{$points[0]}, $_;
: push @{$points[1]}, $data{$_};
: }
 
J

James E Keenan

Jan Fure said:
Hi;

I the code below, I am creating a data structure of array references.
I want to loop through the keys, and for each key, which corresponds
to multiple values, I want to dereference the data to get a plain
array containing the values. I have read 'perlref', but it is still
not clear to me.
I think you're confusing two different aspects of dealing with data
structures. If you are "creating a data structure of array references," you
are concerned with putting data *into* either an array of arrays or a hash
of arrays. But if you "want to dereference the data to get a plain array"
you are concerned with getting data *out* of a pre-existing hash of arrays.
(Your use of the term "key" effectively narrows the choice of data
structures to a hash of arrays.)

How you get data *into* the hash of arrays depends on the data source.
Suppose that the data source is a file which you read line-by-line in a
while() loop and that the raw data looks like this:

alpha gomez halter icicle
beta halter jocular kingdom lambda
gamma beta gomez lambda zebra

....where you can for arbitrary reasons assume that the first word in each
line can serve as a unique identifier for that line. Then you can load up
your data structure like this:

my (%data);
while (<FILE>) {
my @line = split; # by default, split on whitespace
$data{$line[0]} = [ @line ];
}

To get data out of this structure, code like this:

foreach (keys %data) {
print "Key: $_\tValues: @{$data{$_}}\n";
}

See if you can reduce your code to this level of simplicity. My hunch is
that the example you took from the Cookbook is more elaborate than you
really need and that that is confusing you. Also, get the code to do what
you want *without sorting the keys first*. If you aren't clear on what
you're doing, throwing in the sort function will only confuse you more.
HTH.
 
J

Jan Fure

Could you phrase that in the form of a question? It's not clear what
you are misunderstanding.

Given data of the form:

1 2 4
1 2 5
1 3 4.5
2 2 6
2 3 7

How can I order it like:
([1,(2 2 3), (4 5 4.5)], [2, (2 3), (6 7)])

In verbal form, I want to group the values from columns 2 to n by
those corresponding to the same value in column 1, for further
processing for the purpose of finding mean, median, standard deviation
etc.

The ultimate goal is to get an output file like:

1 2.333 4.5
2 2.5 6.5

for the data above in the case of mean/average. To get this, I need to
have some array to loop through, and calculate the statistics for each
row.

In my first post, I showed the code which generated a data structure
with multiple data pairs with the same key, but I am stuck at that
point, as my understanding of referencing is too poor to properly
access the data.
Data::Dumper showed me that the data appears to be properly ordered.

Jan Fure
 
M

Michael Budash

(e-mail address removed) (Jay Tilton) wrote in message
Could you phrase that in the form of a question? It's not clear what
you are misunderstanding.

Given data of the form:

1 2 4
1 2 5
1 3 4.5
2 2 6
2 3 7

How can I order it like:
([1,(2 2 3), (4 5 4.5)], [2, (2 3), (6 7)])

In verbal form, I want to group the values from columns 2 to n by
those corresponding to the same value in column 1, for further
processing for the purpose of finding mean, median, standard deviation
etc.

The ultimate goal is to get an output file like:

1 2.333 4.5
2 2.5 6.5

for the data above in the case of mean/average. To get this, I need to
have some array to loop through, and calculate the statistics for each
row.

In my first post, I showed the code which generated a data structure
with multiple data pairs with the same key, but I am stuck at that
point, as my understanding of referencing is too poor to properly
access the data.
Data::Dumper showed me that the data appears to be properly ordered.

Jan Fure

one way:

#---------------------------------------------------
use strict;
use Data::Dumper;

my @data = ("1 2 4",
"1 2 5",
"1 3 4.5",
"2 2 6",
"2 3 7",
);

my %hash;
foreach (@data) {
my @values = split /\s+/;
foreach my $i (1..$#values) {
push @{$hash{$values[0]}->[$i-1]}, $values[$i];
}
}

my @final;
foreach (sort keys %hash) {
push @final, [ $_, @{$hash{$_}} ];
}

print Dumper(@final);
#---------------------------------------------------

yields:

$VAR1 = [
'1',
[
'2',
'2',
'3'
],
[
'4',
'5',
'4.5'
]
];
$VAR2 = [
'2',
[
'2',
'3'
],
[
'6',
'7'
]
];
 
J

John W. Krahn

Jan said:
Given data of the form:

1 2 4
1 2 5
1 3 4.5
2 2 6
2 3 7

How can I order it like:
([1,(2 2 3), (4 5 4.5)], [2, (2 3), (6 7)])

In verbal form, I want to group the values from columns 2 to n by
those corresponding to the same value in column 1, for further
processing for the purpose of finding mean, median, standard deviation
etc.

The ultimate goal is to get an output file like:

1 2.333 4.5
2 2.5 6.5


Here is one way to do it:

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

my %data;
my @keys;
while ( <DATA> ) {
my ( $key, @data ) = split;
push @keys, $key unless exists $data{ $key };
push @{ $data{ $key }[ $_ ] }, $data[ $_ ] for 0 .. $#data;
}

for my $key ( @keys ) {
print $key;
for my $array ( @{ $data{ $key } } ) {
my $sum;
$sum += $_ for @$array;
( my $avg = $sum / @$array ) =~ s/(\.\d{3})\d+/$1/;
print " $avg";
}
print "\n";
}

__DATA__
1 2 4
1 2 5
1 3 4.5
2 2 6
2 3 7


John
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top