Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

multiple keys hash with array as a value - loop

by grandagent (Novice)
on Dec 08, 2021 at 15:40 UTC ( [id://11139473]=perlquestion: print w/replies, xml ) Need Help??

grandagent has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash which looks somewhat like this ( it has multiple keys for "connection-id" and "username"

$VAR1 = { 'connection-id' => { 'username' => [ value 1, value 2 ], } .... }

What I want to do is loop through that hash and make a string comparison to "value 2" for each of the users but it only give me the first user in the hash, I don't understand why. Appreciate your feedback in advance. This is my loop

foreach my $connection (keys %h) { foreach my $userid (keys %{$h{$connection}}) { @a_ref = @{$h{$connection}{$userid}}; if(lc($userid) eq "rmdb_dbo") { print @a_ref, if ( $a_ref[1] =~ m/update\s +*[table\s*]rmdb_dbo./i ); } } }

Replies are listed 'Best First'.
Re: multiple keys hash with array as a value - loop
by Limbic~Region (Chancellor) on Dec 08, 2021 at 15:50 UTC
    grandagent,
    You said "but it only give me the first user in the hash" when what you should have said is "it only produces output for user rmdb_dbo". That's because your if condition is only displaying output for that user. Try this to debug:
    for my $connection (keys %h) { print "Looking at connection '$connection'\n"; for my $userid (keys %{$h{$connection}}) { print "\tLooking at userid '$userid'\n"; @a_ref = @{$h{$connection}{$userid}}; if(lc($userid) eq "rmdb_dbo") { print @a_ref, if ( $a_ref[1] =~ m/update\s*[table\s*]rmdb_ +dbo./i ); } else { print "Not checking '@a_ref' because user is not 'rmdb_dbo +'\n"; } } }

    Cheers - L~R

      My description was a bit confusing I admit. I just used "value1" "value2" as a placeholder. The acutall strings look like this:
      value1 = UID="rmdb_dbo";DBN=234952;... value2 = update rmdb_dbo....

      where value2 can be also "insert/delete ..." and so on (any type of SQL statement)

      rmdb_dbo is the user that can have multiple connections i.e. multiple connection-id's for that particular user

      Cheers
Re: multiple keys hash with array as a value - loop
by choroba (Cardinal) on Dec 08, 2021 at 15:50 UTC
    The code snippets don't correspond to each other. value 2 doesn't match /update\s*[table\s*]rmdb_dbo./i'. Moreover, the string 'table in the square brackets seems like a meaningful word, but square brackets introduce character classes, so [table\s*] in fact matches a single character a, b, e, l, t, asterisk, or whitespace.

    Try to post runnable code like the following:

    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; my %h = ( 'connection-id0' => { username1 => ['value 1', 'value 2'], username2 => [ 'value5' ], }, 'connection-id1' => { username1 => ['value 2', 'value 3'], }, 'connection-id2' => { username1 => ['value 3', 'value 4'], } ); for my $connection (keys %h) { foreach my $userid (keys %{ $h{$connection} }) { my @ar = @{ $h{$connection}{$userid} }; if (lc $userid eq 'username1') { say "@ar" if grep /value 2/i, @ar; } } }
    I used grep so the "value 2" might be located anywhere in the array.
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Thanks for the reply "value1/2" are not the acutal strings those are just placeholders. The string looks like this
      value1="UID=rmdb_dbo;DBN=326474...."
      (UID can have different usernames, I just picked rmdb_dbo as an example but it can also be a personal user like "cb2ayal" for example) value2 can be any SQL string like the below
      "update ..." "insert ..." "delete ..."
      I am insterest in the tables with "rmdb_dbo" so I need to grep for this string
Re: multiple keys hash with array as a value - loop
by LanX (Saint) on Dec 08, 2021 at 17:03 UTC
    borrowing the data from choroba

    use v5.12; use warnings; my $h = { 'connection-id0' => { username1 => ['value 1', 'value 2'], username2 => [ 'value5' ], }, 'connection-id1' => { username1 => ['value 2', 'value 3'], }, 'connection-id2' => { username1 => ['value 3', 'value 4'], } }; while ( my ( $con, $h_users) = each %$h ){ while ( my ($user, $a_vals) = each %$h_users ) { my $val = $a_vals->[1] // ""; say "Found $con -> $user -> $val" if $val =~ /value/; } }
    OUTPUT:
    Found connection-id2 -> username1 -> value 4 Found connection-id1 -> username1 -> value 3 Found connection-id0 -> username1 -> value 2

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Re: multiple keys hash with array as a value - loop
by AnomalousMonk (Archbishop) on Dec 09, 2021 at 03:35 UTC

    And I'll bring up the rear again with the note that the Perl Data Structures Cookbook (perldsc) discusses the handling of complex data structures such as a Hash of a Hash of Arrays (HoHoA).


    Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11139473]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (2)
As of 2024-04-25 06:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found