Comparing 2 hashes of array refs

Ask a Question related to PERL Miscellaneous, Design and Development.

  1. #1

    Default 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]
    );


    > 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";
    > }
    > }
    > }
    > }
    (snipped)



    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

  2. Similar Questions and Discussions

    1. 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...
    2. 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...
    3. 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} = ; ...
    4. 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>; ...
    5. 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"; } ...
  3. #2

    Default Re: Comparing 2 hashes of array refs

    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]}
    >
    > 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! :-(
    >
    I know I'm not answering your question directly, but I think you might
    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

  4. #3

    Default 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

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139