Ask a Question related to PERL Miscellaneous, Design and Development.
-
Steven Kuo #1
Re: Comparing 2 hashes of array refs
On 11 Jul 2003, simo wrote:
> Hi, I've been working on this for days and don't seem to be getting
> very far.
>
> I have a hash of task titles which holds an array of permissions
> needed to do those tasks:
>
> my %task = {'gardening' => [1,2,6], 'cleaning' => [3,2,5]}
>
> And then I have an array of permissions that the user has, which I put
> into a hash so that the data formats would be similar, although it
> might not be helping, basically the permissions array is [1,4] for
> this example:
>
> my %permissions = {'gardening' => [1,4], 'cleaning' => [1,4]}
It's best to cut and paste from your code, as opposed to retyping.
Hashes are defined by parenthesis, not by curly brackets. E.g.,
my %permissions = (
gardening => [1,4],
cleaning => [1,4]
);
(snipped)> So I basically have to loop through each task, checking to see if I
> have permission to do it (if any of 1,4 are included then I have
> permission, so it's 1 OR 4, not 1 AND 4).
>
> So it's kinda like comparing each array reference in the task hash
> with each element in the permissions array, but I can't do it! :-(
>
> The following is some debugging script I'm using to inspect each
> element and compare it, but it's not working. %script_task_hash is the
> task hash defined in my script, %file_task_hash is the permissions
> hash defined in a CSV file I'm reading in:
>
> # loop through script task hash - key is task
> foreach $task (keys %script_task_hash) {
> foreach $sth_array_value (@{$script_task_hash{$task}}) {
> print "stask: $task / permission: $sth_array_value \n";
>
> foreach $fth_array_value (@{$file_task_hash{$task}}) {
> print "ftask: $task / permission: $fth_array_value \n";
> if ($fth_array_value ne $sth_array_value) {
> print "$task cannot be performed \n";
> }
> else {
> print "$task can be performed \n";
> }
> }
> }
> }
Your description doesn't match the subject line; I inferred that
you wanted something like this:
use strict;
use warnings;
my %task = (
gardening => [1,2,6],
cleaning => [3,2,5],
);
my %permissions = (
gardening => [1,4],
cleaning => [1,4],
);
while (my ($task,$aref) = each %task) {
my %p = map { $_ => 1 } @{$permissions{$task}};
if (grep exists $p{$_}, @$aref) {
print "Can do $task\n";
} else {
print "Extnay on $task\n";
}
}
--
Hope this helps,
Steven
Steven Kuo Guest
-
Distributing an array of hash refs across a table?
I have a cgi script that polls a SQL database and prints out reports. some of the reports have more columns then others. I assume (yes I know... -
Printing Array of Hashes
Hi John, I received your code. Thanks. I would like to know how to check the values of the keys in the hash. I checked the Perl cookbook and... -
Comparing Hashes with different keys. How ?
Hi, I have two different hashes built from separate data and need to find the common then differing items. $HoA1{$custnum} = ; $HoA2{$uid} = ; ... -
Slice an array of hashes?
Is it possible to slice a list of hashes? I read in data into the @data array as follows: while ( $i < $numLev ) { $line = <$fh>; ... -
adding to an array of hashes
When I run the following: for($k=0;$k<3;$k++){ $r->{'NUM'} = $k; #$temp->{'NUM'} = $k; #$r = $temp; print "added: $r->{'NUM'}\n"; } ... -
Steve May #2
Re: Comparing 2 hashes of array refs
simo wrote:
I know I'm not answering your question directly, but I think you might> Hi, I've been working on this for days and don't seem to be getting
> very far.
>
> I have a hash of task titles which holds an array of permissions
> needed to do those tasks:
>
> my %task = {'gardening' => [1,2,6], 'cleaning' => [3,2,5]}
>
> And then I have an array of permissions that the user has, which I put
> into a hash so that the data formats would be similar, although it
> might not be helping, basically the permissions array is [1,4] for
> this example:
>
> my %permissions = {'gardening' => [1,4], 'cleaning' => [1,4]}
>
> So I basically have to loop through each task, checking to see if I
> have permission to do it (if any of 1,4 are included then I have
> permission, so it's 1 OR 4, not 1 AND 4).
>
> So it's kinda like comparing each array reference in the task hash
> with each element in the permissions array, but I can't do it! :-(
>
consider a different approach.
I use sort of the same concept to control access to my programs, but
use a hash of hashes instead. Seems a lot cleaner than fiddling with
lists, at least at first glance.
So I have:
%hash = ( module1 => { tool1=>1, tool2=>1, tool3=>1 },
module2 => { tool1=>1, tool2=>1, tool3=>1 },
);
A users permission hash might look like:
%hash = { module1 =>{ tool2=>1, tool3=>1 } );
So the user could only access tool2 and tool3 in module1.
Simplified example:
my %hash = &load_permissions( 'user_id' );
my $module = 'module2';
my $tool = 'tool1';
if( $hash{$module}{$tool} ){ &do_work( $module, $tool ); }
else{ &show_default; }
I store the permission hashes for each user in a database and eval them
as needed. (uh... I also do some other things to increase efficiency)
Just a thought.....
s.
Steve May Guest
-
Jay Tilton #3
Re: Comparing 2 hashes of array refs
[email]simoninusa2001@yahoo.co.uk[/email] (simo) wrote:
: I have a hash of task titles which holds an array of permissions
: needed to do those tasks:
:
: my %task = {'gardening' => [1,2,6], 'cleaning' => [3,2,5]}
:
: And then I have an array of permissions that the user has, which I put
: into a hash so that the data formats would be similar, although it
: might not be helping, basically the permissions array is [1,4] for
: this example:
:
: my %permissions = {'gardening' => [1,4], 'cleaning' => [1,4]}
:
: So I basically have to loop through each task, checking to see if I
: have permission to do it (if any of 1,4 are included then I have
: permission, so it's 1 OR 4, not 1 AND 4).
:
: So it's kinda like comparing each array reference in the task hash
: with each element in the permissions array, but I can't do it! :-(
Building a set of nested iterations just to find the intersection of
two arrays is for the birds.
Nested...birds...that's a joke, son!
See perlfaq4, "How do I compute the difference of two arrays? How do
I compute the intersection of two arrays?"
for( keys %task ) {
if( isect( $task{$_}, $permissions{$_} ) ) {
print "$_ can be performed\n"
}
else {
print "$_ cannot be performed\n"
}
}
sub isect {
my($a1, $a2) = @_;
my %seen = map( ($_, 1), @$a1 );
grep $seen{$_}, @$a2;
}
Or, just because the array values permit it,
for( keys %task ) {
my($t, $p) = (0,0);
vec($t, $_, 1) = 1 for @{$task{$_}};
vec($p, $_, 1) = 1 for @{$permissions{$_}};
if( $t & $p ) {
print "$_ can be performed\n"
}
else {
print "$_ cannot be performed\n"
}
}
: I also tried this earlier, but think it's worse than the first one, as
: it uses grep which the perldoc/faq says not to do!
Feh. The FAQ advises against using grep() in void context. You're
using it in a scalar (boolean) context. Anyway, discarding a puny
two-item list returned by grep() isn't going to hurt anything.
: So I'd be able to garden, but not clean.
That's good. Gardening while cleaning only makes the cleaning harder.
Jay Tilton Guest



Reply With Quote

