Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

checking the string against all values of multidimension hashmap in perl

by learnP (Initiate)
on Nov 20, 2013 at 15:17 UTC ( [id://1063542]=perlquestion: print w/replies, xml ) Need Help??

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

I have the below requirements * Read the sample data file /tmp/user_defined_connection.ini

MANAGEMENT=IDL||CIDL NORTH=IDL,NORTHERN||VIDL,NORTH||IDL,NORTH SOUTH=IDL,SOUTHERN||CIDL,SOUTH||IDL,SOUTH

Each Key here can have the multiple such values ',' signifies an AND operations and '||' is an OR operation * I need to check this against another string $instance and for each value , so I take the first key MANAGEMENT and get its values and check against isntance .... `$instance` contains `IDL` or `CIDL` In next iteration same instance will be checked against the second key which is `NORTH` and if true the function should return NORTH so basically I need to check the instance against each value one by one and then return the key which i find the last... below is the code written till now

How the check should work in this example checks if InterfaceAlias contains (IDL OR CIDL) , then checks if same interfaceAlias contains [(IDL AND NORTH) OR (VIDL AND NORTH) OR (IDL AND NORTHERN) , then checks if same interfaceAlias contains (IDL AND SOUTH) OR (CIDL AND SOUTH) OR (IDL AND SOUTHERN) So we have to check against all values in hash %idlcodes and return the last key with which match was TRUE The sequence is managed by the array `@providerCloudSequence` Adjacency of words is not important For example SOUTH_XXX_CIDL or even "SOUTH IDL IPV WITH SPACES" should match SOUTH_IPV....These are just examples it is basically a contains match....though the structure of file is fixed...(the data may vary)

#!/sbin/perl -w use strict; use Data::Dumper; my @providerCloudSequence; my %idlcodes; open(my $iniFH, '<', '/tmp/user_defined_connection.ini') or die "Unable to open file:$!\n"; while(<$iniFH>) { chomp; my @providerCloudClass = split('=',$_); push @providerCloudSequence, $providerCloudClass[0]; if ($@) { print "Script Failed to get the Sequence....Exiting the Sc +ript\n"; exit 1; } #my %idlcodes = map { split /=|\s+/; } <$iniFH>; my ($k, @r) = split /=|\Q||/; $idlcodes{$k} = [ map [ split /,/ ], @r ]; } if($@){ print "Script Failed to create the hash....Exiting the Scr +ipt\n"; exit 1; } close $iniFH; print Dumper \%idlcodes; my @interfaceSampleAliases = { "AFGHD_NORTH", "NORTHERN_IIDID_IPV123" +, "IDL_SOUTH", "IDL_SOUTH_IUID", "SOUTHERN_IND_IPV" }; foreach (@interfaceSampleAliases){ my $correctKey = getCorrectKey($_, %idlcodes, @provide +rCloudSequence) print $correctKey; } } # Providercloudsequence helps to maintain the precedence of the in +put file # idlcodes is the hasp map where key is the key from file and valu +e is an arracy of arrays ...see below the output of same sub getCorrectKey($$$){ my $interfaceAlias = $_[0]; foreach ($_[2]) { # This is where I need the help , I want to get the value from + # hash %idlcodes using the key from @providerCloudSequence # The value of %idlcodes is kind of multiple Arrays where I wa +nt to # grep $interfaceAlias against each with a AND in between elem +ents # and OR in between arrays , if true this is match } } ##Data Dumper Output : Hash looks like 'NORTH_IPV' => [ [ 'IDL', 'NORTHERN' ], [ 'VIDL', 'NORTH' ], [ 'IDL', 'NORTH' ] ], 'MANAGEMENT' => [ [ 'IDL' ], [ 'CIDL' ] ], 'SOUTH_IPV' => [ [ 'IDL', 'SOUTHERN' ], [ 'CIDL', 'SOUTH' ], [ 'IDL', 'SOUTH' ] ] <p><b> #### Expected output InterfaceAlias correctKey "AFGHD_NORTH" Doesnt Match anything so return NULL "NORTHERN_IIDID_IPV123" Doesnt Match anything so return NULL "IDL_SOUTH", SOUTH_IPV "IDL_SOUTH_IUID", SOUTH_IPV "SOUTHERN_IND_IPV" Doesnt Match anything so return NULL "IDL_NORTH_IPV" NORTH_IPV "IDL_ABDGJF" MANAGEMENT </b></p>

Replies are listed 'Best First'.
Re: checking the string against all values of multidimension hashmap in perl
by Kenosis (Priest) on Nov 20, 2013 at 19:39 UTC

    Perhaps the following will be helpful:

    use strict; use warnings; my %hash; my @interfaceSampleAliases = ( "AFGHD_NORTH", "NORTHERN_IIDID_IPV123", "IDL_SOUTH", "IDL_SOUTH_IUID", "SOUTHERN_IND_IPV", "IDL_NORTH_IPV", "IDL_ABDGJF" ); chomp( my @iniFileData = <DATA> ); initInterfaceAliasHash( \%hash, \@iniFileData ); for my $interface (@interfaceSampleAliases) { if ( my $key = findInterfaceAlias( \%hash, \$interface ) ) { print "'$interface' matches key: $key\n"; } else { print "'$interface': No match\n"; } } sub initInterfaceAliasHash { my ( $hashRef, $iniFileDataRef ) = @_; my $i = 1; for (@$iniFileDataRef) { my @ands; my ( $key, $val ) = split /=/; my @ors = split /\|\|/, $val; for my $or (@ors) { push @ands, join '', map { "(?=.*\\b\Q$_\E\\b)" } split /, +/, $or; } $$hashRef{ $i++ }{$key} = join '|', map { "(?:$_)" } @ands; } } sub findInterfaceAlias { my ( $hashRef, $interfaceAliasRef ) = @_; my $lastMatch = 0; my $interfaceAlias = $$interfaceAliasRef; $interfaceAlias =~ s/_/ /g; for my $key1 ( sort { $a <=> $b } keys %$hashRef ) { my $key2 = ( keys $$hashRef{$key1} )[0]; $lastMatch = $key1 if $interfaceAlias =~ /$$hashRef{$key1}{$key2}/ and $key1 > $lastMatch; } return ( keys $$hashRef{$lastMatch} )[0] if $lastMatch; } __DATA__ MANAGEMENT=IDL||CIDL NORTH_IPV=IDL,NORTHERN||VIDL,NORTH||IDL,NORTH SOUTH_IPV=IDL,SOUTHERN||CIDL,SOUTH||IDL,SOUTH

    Output:

    'AFGHD_NORTH': No match 'NORTHERN_IIDID_IPV123': No match 'IDL_SOUTH' matches key: SOUTH_IPV 'IDL_SOUTH_IUID' matches key: SOUTH_IPV 'SOUTHERN_IND_IPV': No match 'IDL_NORTH_IPV' matches key: NORTH_IPV 'IDL_ABDGJF' matches key: MANAGEMENT

    All subroutines take references. The subroutine initInterfaceAliasHash() takes a hash reference and an array reference. The array reference is a reference to an array that holds the chomped lines of the ini file. The hash of hashes (HoH) that's built uses the order of the lines as keys to Interface Aliases as keys and the associated values that are regexes which do the and/or logic. Here's a Dumper of the hash that created above:

    $VAR1 = { '1' => { 'MANAGEMENT' => '(?:(?=.*\\bIDL\\b))|(?:(?=.*\\bCID +L\\b))' }, '3' => { 'SOUTH_IPV' => '(?:(?=.*\\bIDL\\b)(?=.*\\bSOUTHERN\ +\b))|(?:(?=.*\\bCIDL\\b)(?=.*\\bSOUTH\\b))|(?:(?=.*\\bIDL\\b)(?=.*\\b +SOUTH\\b))' }, '2' => { 'NORTH_IPV' => '(?:(?=.*\\bIDL\\b)(?=.*\\bNORTHERN\ +\b))|(?:(?=.*\\bVIDL\\b)(?=.*\\bNORTH\\b))|(?:(?=.*\\bIDL\\b)(?=.*\\b +NORTH\\b))' } };

    To check an Interface Alias, send a hash reference and a reference to the string that holds the Interface Alias to the subroutine findInterfaceAlias(). If there was a match, the key from the last successful match will be returned, else NULL is returned.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-19 04:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found