Re: Array of Hashes
by japhy (Canon) on Sep 20, 2005 at 17:31 UTC
|
You'll have to loop over the array, like so:
my $wanted;
for my $href (@outputFiles) {
$wanted = $href, last if exists $href->{$captureId};
}
My code gives you $wanted which IS the hash reference, rather than the index in the array. You'd print $wanted->{$captureId} and $wanted->{type}.
If you don't have duplicate hash keys, though, why are you using an array of hash refs?
| [reply] [d/l] [select] |
|
|
Thanks that works!
<If you don't have duplicate hash keys, though, why are you using an array of hash refs?>
I will not have duplicate captureID's. But I want to record the data in the following table using some Perl data structure.
captureID | outputFileLocation| Filetype
------------|--------------------|---------
captureID1 | c:/temp/test.xml | 4
captureID2 | c:/test/temp.xml | 6 ......
In this captureID is unique. Is there any other way of handling this data other than array of hashes?
| [reply] |
|
|
Is there any other way of handling this data...
Since all the "captureID" values are unique, and these are the values that you want to use for fetching information about a given entry, I guess the question is, "why use an array at all?" I think a HoH (or even a simple hash) would work just as well:
my %outputFiles;
sub setOutputFile
{
my ($id,$path,$type) = @_;
# HoH method:
$outputFiles{$id}{path} = $path;
$outputFiles{$id}{type} = $type;
# or, simple hash method:
# $outputFiles{$id} = join "=:=", $type, $path;
}
sub getOutputFiles
{
my $id = shift;
# HoH method:
my $type = $outputFiles{$id}{type};
my $path = $outputFiles{$id}{path};
# or, simple hash method:
# my ( $type, $path ) = split /=:=/, $outputFiles{$id};
# ... do something with $path and $type ...
}
| [reply] [d/l] |
|
|
But though it is less efficient?
Could you not keep a second index. Or multiple indicies?
Or is there a better way. I am asking since I am holding data from a database in a loh for html::template's happiness and the second index prevents a linear scan each time.
%primary_key{ $capture_id } = $array_index;
| [reply] |
Re: Array of Hashes
by friedo (Prior) on Sep 20, 2005 at 17:33 UTC
|
It's easy to get the element (or elements, since there can be more than one) directly by using grep.
my @elements = grep { exists $_->{$captureId} } @outputFiles;
If you really want the index of the element, rather than the element itself, you can change the grep to:
my @indexes = grep {
exists $outputFiles[$_]{$captureId}
} 0..$#outputFiles;
| [reply] [d/l] [select] |
|
|
Thanks friedo. But I am getting the following error when trying to run your code.
"Modification of a read-only value attempted at" the following line.
my @elements = grep { exists $_->{$captureId} } @outputFiles;
| [reply] [d/l] |
|
|
I don't get that error. Are you certain that what you have is an array of hashes? Here is a one-liner which shows that it works:
perl -Mstrict -Mwarnings -MData::Dumper -e
'my @array = ( { foo => 1 }, { }, { }, { foo => 2 } ); my
@elements = grep { exists $_->{foo} } @array; print Dumper
\@elements'
$VAR1 = [
{
'foo' => 1
},
{
'foo' => 2
}
];
| [reply] [d/l] |
Re: Array of Hashes
by graff (Chancellor) on Sep 20, 2005 at 17:48 UTC
|
Now that friedo japhy has given you the answer you want, let me suggest that your "setOutputFiles" sub should be using "push" rather than referencing a global-scope array index variable (especially since, in the code you posted, it looks like you might forget to increment the global instance of $count). How about:
sub setOutputFiles
{
my ($captureId,$outputFile,$fileType) = @_;
push @outputFiles, { $captureId => $outputFile,
'type' => $fileType };
print Dumper(\@outputFiles);
}
Either that, or else you'll want to pass an array index value in the call to this sub (e.g. in case you want to assign different values to an existing array element). | [reply] [d/l] |