CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Manipulating a Hash with keys that have more than one value

 

First page Previous page 1 2 Next page Last page  View All


spuds
Novice

Mar 12, 2011, 10:10 AM

Post #1 of 35 (6386 views)
Manipulating a Hash with keys that have more than one value Can't Post

Hi,

I am trying to use a Hash that has 2 values per key. I need to sort on the 2nd value (a number), then delete all of the 2nd number values in the Hash - all the while keeping the sorted numeric order of the Hash.

I am currently getting a "can't coerce array into hash" (inside the subroutine below).

Here is what I have so far:
------------------------------------------------------------------
#!/usr/bin/per -w

use Data::Dumper;

my @rules;

# test data
my $ruleKey1 = "aRule";
my $contents1 = "rulenumber=1";
my $rulenumber1 = 1;

my $ruleKey3 = "cRule";
my $contents3 = "rulenumber=3";
my $rulenumber3 = 3;

my $ruleKey2 = "bRule";
my $contents2 = "rulenumber=2";
my $rulenumber2 = 2;

# add keys and their values to an anonymous array
push @{$rules{$ruleKey1}}, $contents1;
push @{$rules{$ruleKey1}}, $rulenumber1;

push @{$rules{$ruleKey3}}, $contents3;
push @{$rules{$ruleKey3}}, $rulenumber3;

push @{$rules{$ruleKey2}}, $contents2;
push @{$rules{$ruleKey2}}, $contents2;

print "\nRules in Ascending Numeric Order:\n";

foreach $ruleKey (sort hashValueAscendingNum (keys{%rules)))
{
print "\t$rules{$ruleKey} \t\t $ruleKey\n";
}

# now need to delete the 2nd value from each key, somehow?
# foreach using the delelte $rules{$ruleKey}->{$ruleNum}
#syntax?

sub hashValueAscendingNum
{
@{$rules{ruleKey1}->{$ruleNum1}} <=> @{$rules{$ruleKey}->{$ruleNum}}

}
------------------------------------------------------------------

Thank you.

- Spuds


Karazam
User

Mar 12, 2011, 12:16 PM

Post #2 of 35 (6382 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

I came up with this.


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

my %rules;

# test data
my $ruleKey1 = "aRule";
my $contents1 = "rulenumber=1";
my $rulenumber1 = 1;

my $ruleKey2 = "bRule";
my $contents2 = "rulenumber=2";
my $rulenumber2 = 2;

my $ruleKey3 = "cRule";
my $contents3 = "rulenumber=3";
my $rulenumber3 = 3;

# add keys and their values to an anonymous array
push @{ $rules{$ruleKey1} }, $contents1;
push @{ $rules{$ruleKey1} }, $rulenumber1;

push @{ $rules{$ruleKey2} }, $contents2;
push @{ $rules{$ruleKey2} }, $rulenumber2;

push @{ $rules{$ruleKey3} }, $contents3;
push @{ $rules{$ruleKey3} }, $rulenumber3;

for my $x ( sortit() ) {
print "$x->[0]\t$x->[1]\n";
}

sub sortit {
map $_->[0],
sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $rules{$_} }[0] ], @{ $rules{$_} }[1] ],
keys %rules;
}


The construct inside the sub is called a Schwartzian Transform, after Randal L. Schwartz. I'll try to walk you through it.

-- Starting from the bottom, the keys in %rules are taken as input to a map (the line above).
-- Inside the map the keys from %rules are stored in $_. We now create an anonymous array with two elements. The second element is the numbers 1,2,3 from the hash. The first element is also an anonymous array with two elements.
-- Move up a line, and the freshly constructed anonymous array is passed to a sort. We want to sort on the second subelement, hence we dereference to [1].
-- The sorted array is returned to yet another map. This one is returning only the first element, while the second is discarded. Remember, that first element was also an anonymous subroutine with two elements. That is returned from the sub.

In the for-loop, $x will be a reference to an anonymous array, we dereference it to get the values we wanted.

By the way, you could also have written


Code
$rules{$ruleKey1} = [ $contents1, $rulenumber1 ];


Hope this helps. Smile


spuds
Novice

Mar 12, 2011, 3:19 PM

Post #3 of 35 (6378 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Thank you very much!

What you did works well though I also have a need to make sure that I don't get 2 rulenumbers of the same value.

I can check earlier in my script but was wondering if there is a way inside the Schwartzian Transform? Maybe a check from the sort function output to a variable and then checking that for a rulenumber of the same value?

Thank you again.

- Spuds


Karazam
User

Mar 12, 2011, 3:30 PM

Post #4 of 35 (6376 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

You mean like this situation?


Code
aRule	rulenumber=1 
bRule rulenumber=2
cRule rulenumber=3
dRule rulenumber=3


If so, what would you want the output to be in that case?

Edit: If you simply want to skip the dRule line, then this modification might be what you need.


Code
for my $x ( sortit() ) {  
print "$x->[0]\t$x->[1]\n" unless $seen{$x->[1]};
$seen{$x->[1]}++;
}



(This post was edited by Karazam on Mar 12, 2011, 3:38 PM)


spuds
Novice

Mar 12, 2011, 3:35 PM

Post #5 of 35 (6374 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Yes, exactly like that. If that happens I want to kill the script with a die and msg to user.

Thank you.


Karazam
User

Mar 12, 2011, 3:42 PM

Post #6 of 35 (6372 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Oh, maybe like this then:


Code
for my $x ( sortit() ) {  
unless ( $seen{$x->[1]} ) {
print "$x->[0]\t$x->[1]\n";
$seen{$x->[1]}++;
}
else {
print STDERR "Oh noes! Duplicate: $x->[0] $x->[1]\n";
die;
}
}



(This post was edited by Karazam on Mar 12, 2011, 3:57 PM)


spuds
Novice

Mar 16, 2011, 6:42 PM

Post #7 of 35 (6336 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi again,

I have moved the code you posted for me into my latest source below:

Code

#!/usr/bin/perl -w

use Data::Dumper;

my %rules;

&get_rules( $path, \%rules );

while (($key, $value) = each %rules)
{
... last work to do with the %rules HoA ...
}


sub get_rules
{
my( $path, $sRules ) = @_;

foreach $file ( @files )
{
# match
if( $file =~ m/$matchRequest/i )
{
...

# add the rule and it's number
$rulenumber = &add_rule( $data );

# need to store each new anonymous array record (1 or more arrays) in the HoA here ... is that already being done in the next line ?
# add key and values to anonymous array ( HoA )
$sRules{$file} = [ $data, $rulenumber ];

}
else ...
...
}

# pass a reference to the complete un-sorted HoA
&get_sorted_rules( $sRules );
}

sub get_sorted_rules
{
my( $theRules ) = @_;
my $arrayRef;

for $arrayRef ( sort_rules( $theRules ) )
{
# check for duplicate rules and print out each rule's hash array ref if NOT a duplicate
unless ( $seen{$arrayRef->[1]} )
{
print "$arrayRef->[0]\t$arrayRef->[1]\n";
$seen{$arrayRef->[1]}++;
}
else
{
die "Oh no! Duplicate rule numbers: $arrayRef->[0] $arrayRef->[1]\n";
}
}
}

# sort the rules
sub sort_rules
{
my( $sortRules ) = @_;

map $_->[0],
sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $sortRules{$_} }[0] ], @{ $sortRules{$_} }[1] ],
keys %{$sortRules};
}


Some of the syntax questions I have now are related to using references to the original %rules hash through the subroutine calls.

I was under the assumption that when I reference a hash through subroutine calls that all the references to the same hash would update that hash. Not what I am seeing. Syntax related again? Not so sure. Seems like a local/scoping issue.

I am also having a problem verifying the current data in the updating $file key data in the HoA in the foreach $file loop near the top of this listing. (attempted to use print Dumper...)

I then need to do the &get_sorted_rules( $sRules ); call with all the collected rules in the HoA.

Lastly, I need to do the rules sort with the $rulenumber in the HoA, then remove it and store the remaining data in the HoA so I can use the %rules hash in the while loop near the top of the listing.

I appreciate any further assistance.

Thank you.

- spuds


Karazam
User

Mar 17, 2011, 2:08 AM

Post #8 of 35 (6330 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

When you use a hashref you must dereference it so perl knows it's a hashref and not a newly named hash.


Code
$$sRules{$file} = [ $data, $rulenumber ];


I think the rest of your problems are related to that.
You really should have "use strict;", then you would have gotten the message


Code
Global symbol "%sRules" requires explicit package name at ...


Hope this helps. Smile


spuds
Novice

Mar 18, 2011, 9:36 AM

Post #9 of 35 (6313 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi again,

I have implemented your suggestions and am currently getting a "
Can't use string ("1") as an ARRAY ref while "strict refs" in use at ..." error on the line:

unless ( $seen{$arrayRef->[1]} )
{
...

I am also able to use print Dumper successfully in the get_rules subroutine BUT not in the get_sorted_rules subroutine.

I noticed an article that mentioned there may be strange behavior of args in subroutines, depending on their order the script - could this be what is happening here with Dumper?

Here is the latest relevant code.


Code
#!/usr/bin/perl -w  

use Data::Dumper;
use strict;

my %rules;

&get_rules( $path, $cConn, \%rules);

while (($key, $value) = each %rules)
{
...
}

sub get_rules
{
my $path = shift;
my $cConn = shift;
my(%sRules) = %{( shift )};

foreach $file ( @files )
{
...

# add key and values to anonymous array ( creating an HoA )
$sRules{$file} = [ $data, $rulenumber ];

}
...


print "... current hash content is ... \n\n";

for my $key (keys %sRules)
{
print "$key => $sRules{$key}->[0]";
print "$key => $sRules{$key}->[1]\n";
}

# OUTPUT HERE WORKS FINE ...
print Dumper(%sRules);

&get_sorted_rules( \%sRules );
} # end of get_rules sub

# sort the rules
sub sort_rules
{
my(%snmRules) = %{( shift )};

print "start of the sort_rules sub!\n";

map $_->[0],
sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $snmRules{$_} }[0] ], @{ $snmRules{$_} }[1] ],
keys %snmRules;

print "end of the sort_rules sub!\n";
}

# collect sorted HoA of rules
sub get_sorted_rules
{
my(%snRules) = %{( shift )};

my $arrayRef;
my %seen = ();

print "start of get_sorted_rules sub!\n\n";

# NO OUTPUT HERE ... WHY NOT?
print Dumper(%snRules);

for $arrayRef ( sort_rules( \%snRules ))
{

print "inside the for loop within get_sorted_rules sub!\n\n";
# check for duplicate rules and print out each rule's hash array ref if NOT a duplicate

# ERROR ON NEXT LINE: "Can't use string ("1") as an ARRAY ref while "strict refs" in use ..."
unless ( $seen{$arrayRef->[1]} )
{
print "$arrayRef->[0]\t$arrayRef->[1]\n";
$seen{$arrayRef->[1]}++;
}
else
{
die "Oh no! Duplicate rule numbers: $arrayRef->[0] $arrayRef->[1]\n";
}
}

# can I remove all the rulenumbers like this?
for my $key (keys %snRules)
{
# remove all of the rulenumbers here ... use delete function ...
delete $snRules{$key}->[1];
}

# print "end of get_sorted_rules sub!\n\n";
}


Thank you.

- spuds


Karazam
User

Mar 18, 2011, 10:29 AM

Post #10 of 35 (6308 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Umm well, you have not exactly implemented my suggestion, at least not how I meant it.
I merely suggested that you put an extra dollar sign at this line to dereference the hashref.
(Maybe its typographically hard to see, but it's dollar-dollar-sRules):


Code
$$sRules{$file} = [ $data, $rulenumber ];


Did you try to run the code with only that change, and what happened?

Instead you are now creating a new hash, not a hash ref, inside the subroutine:


Code
my (%sRules) = %{ (shift) };


Maybe that's intentional, but weren't you concerned that the original hash didn't get updated?


spuds
Novice

Mar 18, 2011, 11:42 AM

Post #11 of 35 (6304 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi,

I actually did implement the change you suggested (and it worked) but I saw another example on how to pass the hash from sub to sub so I am using that. Just passing the hash by reference, using 'shift' for the first time, within the subs.

I thought using 'shift' would help with some of the other errors I was seeing (strict global hash ones). Seemed to help.

The current error is attempting to find an array ref for $arrayRef and it's getting a string. I have tried declaring the $arrayRef as a ref like $arrayRef = []; but no luck.

Probably just me again (syntax understanding).

Just wondering how to resolve this error in the get_sorted_rules sub.

Thank you.

- spuds Smile


spuds
Novice

Mar 18, 2011, 12:40 PM

Post #12 of 35 (6300 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Here is the source with the $$ dereferencing ... currently seeing an error where a string is given but hash ref is required. Twice in the get_sorted_rules sub.


Code
 
sub get_rules

my $sRules

foreach $file ( @files )
{
...

# add key and values to anonymous array ( HoA )
$$sRules{$file} = [ $data, $rulenumber ];

}

&get_sorted_rules( %{$sRules} );

} # end get_rules

# collect sorted hash of rules
sub get_sorted_rules
{
my( $snRules ) = shift;
my $arrayRef;
my %seen = ();

print "start of get_sorted_rules sub!\n\n";

# ERROR NEXT LINE HERE: "Can't use string ("abc") as a HASH ref while "strict refs" in use at "
for my $key (keys %{$snRules})
{
print "$key => ${$snRules}{$key}->[0]";
print "$key => ${$snRules}{$key}->[1]\n";
}

# SAME ERROR NEXT LINE HERE: "Can't use string ("abc") as a HASH ref while "strict refs" in use at "
for $arrayRef ( sort_rules( %{$snRules} ))
{

print "inside the for loop within get_sorted_rules sub!\n\n";

# check for duplicate rules and print out each rule's hash array ref if NOT a duplicate
unless ( $seen{$arrayRef->[1]} )
{
print "$arrayRef->[0]\t$arrayRef->[1]\n";
$seen{$arrayRef->[1]}++;
}
else
{
die "Oh no! Duplicate rule numbers: $arrayRef->[0] $arrayRef->[1]\n";
}
}

print "end of get_sorted_rules sub!\n\n";
}
}

# sort the rules
sub sort_rules
{
my( $sbRules ) = shift;

print "start of the sort_rules sub!\n";

map $_->[0],
sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $$sbRules{$_} }[0] ], @{ $$sbRules{$_} }[1] ],
keys %{$sbRules};

print "end of the sort_rules sub!\n";
}


Thank you.

- spuds


Karazam
User

Mar 18, 2011, 1:10 PM

Post #13 of 35 (6297 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

I'm pretty sure this line is the culprit:


Code
&get_sorted_rules( %{$sRules} );


You can only pass scalars as arguments to subroutines, so don't dereference $sRules here. Change it to this:


Code
&get_sorted_rules( $sRules );


Hope this helps. Smile


spuds
Novice

Mar 18, 2011, 6:39 PM

Post #14 of 35 (6279 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi,

Getting "Can't use string ("1") as an ARRAY ref while "strict refs" in use at .." now on the line...

unless ( $seen{$arrayRef->[1]} )


Only changes I made to lastest source above was to change to passing scalers only:

(1) &get_sorted_rules( $sReqRules );

(2) for $arrayRef ( sort_rules( $snRules ))

I've tried to make the $arrayRef a real reference in the declaration but that doesn't seem to help.

Thank you.

- spuds


Karazam
User

Mar 19, 2011, 12:15 AM

Post #15 of 35 (6267 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hmm, well that error occurs when you try to pass an array or hash as argument to a subroutine.
But I see no more place where that might happen in your code, if you took care of those two you describe.

I have taken the liberty of creating a version of your code that I can run on my machine, with a bit of cleaning up of variable names etc.
You can compare it to what you got, hopefully it will help you pinpoint the problem.
The part in get_rules that populates the hash will be different from yours of course.


Code
#!/usr/bin/perl  
use warnings;
use strict;
use Data::Dumper;

my $path = '';
my $cConn = '';
my %rules;

get_rules( $path, $cConn, \%rules );

# print Dumper %rules;

sub get_rules {
my ( $path, $cConn, $href ) = @_;

# part that's different from the original
while (<DATA>) {
my ( $file, $data, $rulenumber ) = split;
$$href{$file} = [ $data, $rulenumber ];
}

for my $key ( keys %{$href} ) {
print "$key => ${$href}{$key}->[0], ";
print "$key => ${$href}{$key}->[1]\n";
}

get_sorted_rules($href);
}

sub get_sorted_rules {
my $href = shift;
my %seen;

for my $aref ( sort_rules($href) ) {
unless ( $seen{ $aref->[1] } ) {
print "$aref->[0]\t$aref->[1]\n";
$seen{ $aref->[1] }++;
}
else {
print STDERR
"Oh no! Duplicate rule numbers: $aref->[0] $aref->[1]\n";
die;
}
}

for my $key ( keys %$href ) {
delete $$href{$key}->[1];
}

# print Dumper $href;
}

sub sort_rules {
my $href = shift;

map $_->[0], sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $$href{$_} }[0] ], @{ $$href{$_} }[1] ],
keys %{$href};
}

__DATA__
aRule rulenumber=1 1
bRule rulenumber=2 2
cRule rulenumber=3 3
dRule rulenumber=4 4



spuds
Novice

Mar 19, 2011, 6:55 AM

Post #16 of 35 (6265 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

I am thinking it may have to do with...

$seen{$arrayRef->[1]}++;

inside here ...


Code
for $arrayRef ( sort_rules( %{$snRules} )) 
{

print "inside the for loop within get_sorted_rules sub!\n\n";
# check for duplicate rules and print out each rule's hash array ref if NOT a duplicate

unless ( $seen{$arrayRef->[1]} )
{
print "$arrayRef->[0]\t$arrayRef->[1]\n";
$seen{$arrayRef->[1]}++;
}
else
{
...
}
}


Is this the proper syntax to increment the $arrayRef? Looks to me like it's being de-referenced properly? and then ++ ...

The string to array ref error may be because perl thinks I am trying increment a reference, instead of the data?

Will look better at the last code you posted see if I can resolve this current error.

Thank you.

- spuds


spuds
Novice

Mar 19, 2011, 7:00 AM

Post #17 of 35 (6264 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

... and no, the argument being passed in NOT currently set to %{$s...} ... just using the scalar reference (copy and paste mistake)...

Thank you.

- spudsCrazy


spuds
Novice

Mar 19, 2011, 12:43 PM

Post #18 of 35 (6251 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi,

I got the script to work using your latest source but see that the %seen hash's array reference is the only time the input rules are in order.

The orginal %rules hash is really what I want updated to the sorted order of rules. (minus all the rulenumbers)

I see when I put a print Dumper call in after the get_rules(\%rules) call that I have the orginal rules in un-sorted order.

When I try to print out all the contents of the anonymous array here:

Code
print "$aref->[0]\t$aref->[1]\n";

I get the sorted data that I need for my now wanted standard key-value only %rules hash. Can I just copy these two values (filename key and contents value) into my %rules hash,
one rule at a time similar to this here?

Code
$href{$aref->[0]} = {$aref->[1]};

Is the %seen hash a special hash in perl? Guessing no, just a meaningful name given to this local scalar.

Thank you.

- spuds


Karazam
User

Mar 19, 2011, 12:51 PM

Post #19 of 35 (6250 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

I don't think there's anything wrong with that bit. The dereference is correct,
as can be seen in the print just above. If you wanna make sure, just comment
the line out and see what happens.

And by the way, the ++ does not increment the $arrayRef, but the value in the hash
%seen which has $arrayRef->[1] as key. That line could have been written as

Code
$seen{$arrayRef->[1]} = 1; 
$seen{$arrayRef->[1]} += 1;
$seen{$arrayRef->[1]} = 'peekaboo';


Its just a way to create a hash entry, the value doesn't matter.


spuds
Novice

Mar 19, 2011, 1:30 PM

Post #20 of 35 (6247 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Hi,

I am trying to either get the sorted rules in the %rules hash (ideally) but am trying right now to put the sorted rules in another global hash called %sortedRules. Here is what I am trying:


Code
# new global hash for sorted rules 
my %sortedRules;

...

unless ($seen{aref->[1]} )
{
print "$aref->[0]\t$aref->[1]\n";
my $filename = $aref->[0];
my $contents = $aref->[1];

$sortedRules{$filename} = $contents;
..
}


Why when I do a print Dumper(%sortedRules) after the get_rules call do I get the unsorted rules? Is there an easier way to get the sorted rules in either %rules or %sortedRules?

Do I have to use the %seen hash?

Thank you.

- spudsSmile


Karazam
User

Mar 19, 2011, 2:37 PM

Post #21 of 35 (6240 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Since you are using references to %rules, that hash will hold the result of your operations.
However, a hash is by its nature not sorted. That is, you don't get things out in the same
order as you put them in. That's how hashes work. If you want to use the sorted data further,
you need to put in a structure that preserves order, that is, an array.
So, try this:


Code
unless ( $seen{ $aref->[1] } ) { 
push @sorted, [ $aref->[0], $aref->[1] ];
$seen{ $aref->[1] }++;
}


And access the data, now in sorted order, by


Code
for my $x ( @sorted ) { 
print "$x->[0] $x->[1]\n";
}


P.S.
With that change, my version of the program now looks like this:


Code
#!/usr/bin/perl  
use warnings;
use strict;
use Data::Dumper;

my $path = '';
my $cConn = '';
my @sorted;

get_rules( $path, $cConn );

for my $aref ( @sorted ) {
print "$aref->[0] $aref->[1]\n";
}

sub get_rules {
my ( $path, $cConn ) = @_;
my %rules;

# replace this part with your own code to populate the hash
while (<DATA>) {
my ( $file, $data, $rulenumber ) = split;
$rules{$file} = [ $data, $rulenumber ];
}

get_sorted_rules( \%rules );
}

sub get_sorted_rules {
my $href = shift;
my %seen;

for my $aref ( sort_rules($href) ) {
unless ( $seen{ $aref->[1] } ) {
push @sorted, [ $aref->[0], $aref->[1] ];
$seen{ $aref->[1] }++;
}
else {
print STDERR "Oh no! Duplicate rule numbers: $aref->[0] $aref->[1]\n";
die;
}
}
}

sub sort_rules {
my $href = shift;
map $_->[0], sort { $a->[1] <=> $b->[1] }
map [ [ $_, @{ $$href{$_} }[0] ], @{ $$href{$_} }[1] ],
keys %{$href};
}

__DATA__
dRule rulenumber=4 4
bRule rulenumber=2 2
cRule rulenumber=3 3
aRule rulenumber=1 1



(This post was edited by Karazam on Mar 19, 2011, 2:58 PM)


spuds
Novice

Mar 20, 2011, 1:16 PM

Post #22 of 35 (6223 views)
Re: [Karazam] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Looks like I still am seeing a problem with a local for loop element $aref.

When I run your


Code
  

sub get_sorted_rules {
my $href = shift;
my %seen;

for my $aref ( sort_rules($href) ) {
unless ( $seen{ $aref->[1] } ) {
push @sorted, [ $aref->[0], $aref->[1] ];
$seen{ $aref->[1] }++;
}
else {
print STDERR "Oh no! Duplicate rule numbers: $aref->[0] $aref->[1]\n";
die;
}
}
}

[\code]

I don't see the problem but when I run my source (all of it) and use the exact same subroutine source (as above) I am seeing my local $aref set to 1 the first time in the loop, not what it should be, an ARRAY(memory location) reference.

I printed out the scalar $aref in both your code and my code (copied from you).

For what's it worth, the ends with this error:


Can't use string ("1") as an ARRAY ref while "strict refs" in use at ... line 279

Here is what I am using:


Code
  

for my $aref ( sort_rules($href) )
273 {
274 print "the number of times thru this for loop $count\n";

# value of $aref is 1 here
275 print "aref is now: $aref\n";
276
277 print "seen hash contains $seen{$aref->[1]}\n\n";
278
279 unless( $seen{$aref->[1]} )
280 {
[\code]

Any ideas on why my $aref is automatically set to 1 the first time, and not the array ref? Fix for this is to set the scalar before I use it... how?

Thank you.

- spuds


spuds
Novice

Mar 20, 2011, 1:36 PM

Post #23 of 35 (6222 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

This is the contents of my hash before I call get_sorted_rules ...

... current hash content is ...

$VAR1 = 'cRule-test';
$VAR2 = [
'# cRule-test rulenumber=8
',
'8'
];
$VAR3 = 'aRule-test';
$VAR4 = [
'# aRule-test ruleNumber=7
',
'7'
];


so this is what I am trying to sort.

Thank you.

- spuds


spuds
Novice

Mar 20, 2011, 3:05 PM

Post #24 of 35 (6214 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post

Believe this might be the culprit... my $rulenumber is a string '7' and not an INT 7 (in above HoA).

I am using this source snippet to get the rulenumber in another subroutine:


Code
  

# get the rulenumber ... "rulenumber=1"
if( $content =~ m/$match(\d+)/ )
{
print "The ruleNumber found is: " . $1 . "\n\n";

if( $1 > MAX_RULES )
{
print STDERR "$fileN has a rule number greater than MAX_RULES. Please use a rule number less than MAX_RULES.\n\n";
die;
}

return ($1);

[\code]

Assuming I need to return an INT, not sure how at the moment though ...

Thank you.

- spuds


Karazam
User

Mar 20, 2011, 3:10 PM

Post #25 of 35 (6214 views)
Re: [spuds] Manipulating a Hash with keys that have more than one value [In reply to] Can't Post


Quote
Any ideas on why my $aref is automatically set to 1 the first time

No, that's strange. But if you still get the "Can't use string ("1") as an ARRAY ref" message,
my guess is that there's still some problem with passing references.

About the hash content... It looks weird, doesn't it? There's one value in $VAR1,
which is then repeated in $VAR2 together with another value in the same array element,
and with a linebreak after it? And why the hash sign?
Looks like it's been created this way:


Code
$rules{"cRule-test"} = [ "# cRule-test rulenumber=8\n", "8" ];


Maybe you need to look at how you populate the hash.


(This post was edited by Karazam on Mar 20, 2011, 3:11 PM)

First page Previous page 1 2 Next page Last page  View All
 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives