Reputation: 993
I have an array with 28 elements.
I copied array contents into a hash.
If i try to print the hash it is not showing all keys and values.
Code is given below,
@new;
%hash = @new;
foreach $food (keys %hash)
{
$color = $hash{$food};
print "$food is $color.\n";
}
Output is ::
attribute is Mandatory.
min is 0X00.
value is 778.
max is 9940486857.
name is Security_header.
type is nibble.
The array @new contents are,
name Protocol_discriminator attribute Mandatory value 778 min 0X00 max 994048685 value 7 min 0 max F name Security_header attribute Mandatory type nibble value 778 min 0X00 max 9940486857
I want all the contents of the array to be copied in the hash and to be printed, if i try to traverse the hash. but some how only part of the array content is copied into the hash.
Can anyone help to overcome this problem. I am struggling for the past two days.
Thanks Senthil.
Upvotes: 2
Views: 522
Reputation: 42095
Simple Answer: A hash should be thought of as an associative array.
There is one unique key and each key has a value (can be a hash).
Your Problem: Every time you encounter a key that already exists, you are replacing the value.
Solution:
#!/usr/bin/perl -w
use strict;
sub main{
$" = ", "; # format array output
my %hash;
my @arr = ( ['color' ,'red' ]
, ['color' ,'blue']
, ['size' ,'1' ]
, ['size' ,'2' ]
);
foreach my $rcd (@arr) {
push @{$hash{$$rcd[0]}} , $$rcd[1];
}
print "@{$hash{color}} \n"; # prints: red, blue
}
main();
Upvotes: 1
Reputation: 139411
Let's change the presentation of @new
to show what's going on:
my @new = qw/
attribute Mandatory
attribute Mandatory
max 994048685
max 9940486857
max F
min 0
min 0X00
min 0X00
name Protocol_discriminator
name Security_header
type nibble
value 7
value 778
value 778
/;
Perl hash keys are unique, so when assigning @new
to %hash
, the last value for a given key “wins.” For a simple example
$ perl -le '%h = qw/1 a 1 b 1 c/; print $h{1}' c
Given that you have many values for the same key, use a data structure that can handle it:
my %hash;
for (my $i = 0; $i < @new; $i += 2) {
my($name,$val) = @new[$i,$i+1];
push @{ $hash{$name} } => $val;
}
If you don't mind destroying @new
, the code can be a little more idiomatic:
while (@new) {
my($name,$val) = splice @new, 0, 2;
push @{ $hash{$name} } => $val;
}
This means every value associated with a given key in %hash
is a reference to an array of values. The push
operator expects an array and not a reference, so we use @{ ... }
to dereference it.
If you aren't familiar with Perl references, be sure to read the perlref and perllol documentation.
One way to print the values in %hash
is
foreach my $name (sort keys %hash) {
print "$name = [@{ $hash{$name} }]\n";
}
Output:
attribute = [Mandatory Mandatory] max = [994048685 9940486857 F] min = [0 0X00 0X00] name = [Protocol_discriminator Security_header] type = [nibble] value = [7 778 778]
Another handy trick for printing and debugging complex data structures is the Data::Dumper
module:
use Data::Dumper;
print Dumper \%hash;
which prints
$VAR1 = {
'attribute' => [
'Mandatory',
'Mandatory'
],
'value' => [
'7',
'778',
'778'
],
'min' => [
'0',
'0X00',
'0X00'
],
'name' => [
'Protocol_discriminator',
'Security_header'
],
'max' => [
'994048685',
'9940486857',
'F'
],
'type' => [
'nibble'
]
};
Upvotes: 6
Reputation: 42411
The information in the @new
array suggests that you need a richer data structure. I don't know the details of your problem, but here's the structure that I see.
my @data = (
# Each data item is a hash reference, with four
# possible keys: name, attribute, type, and vals.
# I added the 'vals' key to handle the other information.
{
name => 'Protocol_discriminator',
attribute => 'Mandatory',
type => undef,
# The 'vals' key points to an array reference.
# That array contains a list of hash references.
vals => [
{ value => 778, min => '0X00', max => 994048685 },
{ value => 7, min => 0, max => 'F' },
],
},
# Another data item.
{
name => 'Security_header',
attribute => 'Mandatory',
type => 'nibble',
vals => [
{ value => 778, min => '0X00', max => 9940486857 },
],
},
);
To learn how to work with complex data structures, see perlreftut, perldsc, and perllol.
Also, your scripts should always contain use strict
and use warnings
.
Upvotes: 2
Reputation: 943100
You have multiple keys with the same name, so you are overwriting the data.
You need to rethink your approach.
Possibly you need a smarter algorithm to construct your hash (e.g. putting values in an array ref instead of just as a simple value). Possibly you need to forget about the hash and just loop over the array with a for loop that increments by 2 each time round.
Upvotes: 6