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

Hello monks,

I'd like to compare the 'eth' value of each component against the other 'eth' values of the /other/ components. Not of the same component. I've started with some loops but then it is looking quite awkward and not graceful at all. Surely there's a better path for doing this. I'm thinking about breaking down each COMP component into its own hash to ease doing the comparisons (they are currently read from a config file using Config::Std).

For instance, COMP1->eth1 would be compared against all other COMPn->ethx values where n !=1. Then, COMP1->eth2 would be compared the same. Then, COMP2->eth1 against all other eth values of all other COMP, so on so forth. Only half the quantity of values would have to be compared I presume.

Any suggestions/insights would be greatly appreciated on how to tackle this in good form.

my %components = ( COMP1 => { eth1 => "10.172.9.21/24", eth1_gw => "10.172.1.1", eth2 => "10.172.10.21/24", }, COMP2 => { eth1 => "10.172.9.22/24", eth2 => "10.172.11.21/24", }, COMP3 => { eth1 => "10.172.11.21/24", eth2 => "10.172.13.21/24", eth3 => "10.173.2.98/24", }, );

foreach my $compName (keys %components) { foreach my $param (keys %{$components{$compName}}) { if ($param =~ /eth[0-9]$/) { # [ then loop again through the COMP keys, excluding the current key # ... does not seem nice ] } }

Replies are listed 'Best First'.
Re: Comparing hash values against other hash values
by ig (Vicar) on May 22, 2009 at 02:58 UTC

    You might consider the following:

    use strict; use warnings; my %components = ( COMP1 => { eth1 => "10.172.9.21/24", eth1_gw => "10.172.1.1", eth2 => "10.172.10.21/24", }, COMP2 => { eth1 => "10.172.9.22/24", eth2 => "10.172.11.21/24", }, COMP3 => { eth1 => "10.172.11.21/24", eth2 => "10.172.13.21/24", eth3 => "10.173.2.98/24", }, ); my @components = keys %components; while ( @components > 1 ) { my $comp = shift @components; foreach my $a ( values %{$components{$comp}} ) { foreach my $b ( map { ( values %{$components{$_}} ) } @compone +nts ) { compare( $a, $b ); } } } sub compare { my ( $a, $b ) = @_; print "$a compared with $b\n"; }

    Or it might be more effective to reorganize your data:

    use strict; use warnings; my %components = ( COMP1 => { eth1 => "10.172.9.21/24", eth1_gw => "10.172.1.1", eth2 => "10.172.10.21/24", }, COMP2 => { eth1 => "10.172.9.22/24", eth2 => "10.172.11.21/24", }, COMP3 => { eth1 => "10.172.11.21/24", eth2 => "10.172.13.21/24", eth3 => "10.173.2.98/24", }, ); my %addresses; foreach my $comp ( keys %components ) { foreach my $eth ( keys %{$components{$comp}} ) { push(@{$addresses{$components{$comp}{$eth}}}, "$comp:$eth"); } } foreach my $address ( keys %addresses ) { print "$address: appears on " . join (', ', @{$addresses{$address} +}) . "\n"; }

    The latter doesn't compare the addresses but it does let you easily identify which components have interfaces with the same address.

Re: Comparing hash values against other hash values
by johngg (Canon) on May 22, 2009 at 08:26 UTC

    You could construct a HoA keyed by IP with the values being anonymous arrays of concatenated component and eth. Any array with more than one element will show a positive match.

    use strict; use warnings; use Data::Dumper; my %components = ( COMP1 => { eth1 => q{10.172.9.21/24}, eth1_gw => q{10.172.1.1}, eth2 => q{10.172.10.21/24}, }, COMP2 => { eth1 => q{10.172.9.22/24}, eth2 => q{10.172.11.21/24}, }, COMP3 => { eth1 => q{10.172.11.21/24}, eth2 => q{10.172.13.21/24}, eth3 => q{10.173.2.98/24}, }, ); my %byIP = (); foreach my $comp ( keys %components ) { foreach my $eth ( keys %{ $components{ $comp } } ) { push @{ $byIP{ $components{ $comp }->{ $eth } } }, qq{$comp:$eth}; } } print Data::Dumper->Dumpxs( [ \ %byIP ], [ qw{ *byIP } ] );

    The Data::Dumper output showing that "COMP2 eth2" and "COMP3 eth1" match.

    %byIP = ( '10.172.9.22/24' => [ 'COMP2:eth1' ], '10.172.1.1' => [ 'COMP1:eth1_gw' ], '10.172.10.21/24' => [ 'COMP1:eth2' ], '10.172.9.21/24' => [ 'COMP1:eth1' ], '10.172.11.21/24' => [ 'COMP3:eth1', 'COMP2:eth2' ], '10.173.2.98/24' => [ 'COMP3:eth3' ], '10.172.13.21/24' => [ 'COMP3:eth2' ] );

    I hope this is useful.

    Cheers,

    JohnGG

    Update: Sorry, I should have read ig's reply properly before posting this. My solutions is essentially identical to his second solution. Please ++ his post, not mine.

      Update: Sorry, I should have read ig's reply properly before posting this. My solutions is essentially identical to his second solution. Please ++ his post, not mine.
      But the documentation was clearer on yours. ++ both in any case.

      Buy This signature on eBay