Joe, Thank you for taking the time to explain this bit of code. I have spent some time trying to understand the ternary operator (?:) this evening and I think it is making more sense. In the past I have seen this operator and moved on in favor of using if/then/else statements but I can see how in this example it is much simpler to evaluate the EXPR with a ternary than to use code blocks. I can now see mostly how this expression works in your example. I see that the first expression says $actual{$_} equal $register{$_} if this is true then $_ equals the hostname. But, if this statement is false then I see that we dereference the $_ values in both Arrays.
When I do run this code though it seems to print out the memory address for the hostname reference which I think means it is not being dereferenced correctly but I don't see how it differs form the else part of the print statement ARRAY(0x816e00c) differs:actual 164.72.119.175 <-> register 164.72.119.179 ARRAY(0x816e03c) differs:actual 164.72.123.43 <-> register 164.72.21.43 host3 is ok ARRAY(0x819bed4) differs:actual 164.72.98.89 <-> register 164.72.8.89 host5 is ok I still have some ways to go with really understanding this but I am closer. Well again thanks for your help, -angus P.s. Your English is probably better than mine; I wouldn't know it wasn't your first language if you didn't mention it. -----Original Message----- From: John Doe [mailto:[EMAIL PROTECTED] Sent: Thursday, February 02, 2006 3:26 AM To: beginners@perl.org Subject: Re: How to compare hashes to find matching keys with conflicting values. Angus am Donnerstag, 2. Februar 2006 10.14: > John, Hello Angus > Well that works perfect now my issue is to understand what you have > provided for me. I see that we are creating an array called res however I > am not sure what map is doing. I did read the perldoc info on map but I am > still confused on how it is being used here. I see from the perldoc that I > could use it like this > > %register = map {$register($) => $_ @array; > print "@array\n"; No, this is syntactically incorrect and wouldn't do anything useful. > This would I think create an array based on the values contained in the > register hash. No; in an assignement <anything> = <anything_else> the left part is made from the expression on the right. > But, I would have now way to link them back to the keys > from register as now they would be numerically ordered in the array instead > of being linked to the hostname key. > > So I am looking at your example: > %actual = map ($actual{$_} eq $register{$_}) This is not my example... and syntactically incorrect. > This I think says each key eq to the other key value. The part within the braces does a comparison between $actual{$_} and $register{$_}. Result is true or false. > Next you use a ? mark which I understand means that the previous > values are optional, No, its part of the ternary ?: operator (see perldoc perlop). my $var = $x ? $y : $z is the same as my $var; if ($x) { $var=$y; } else { $var=$z; } > which > in this case if the are not equal are they then not included in the $_ > variable. But if they are eq then they are included in the $_ value which > means they are placed back into the hashes? After this the register hash > is sorted but I don't understand why. It's because of the sort (see perldoc -f sort) in the expression. The keys of %keys are sorted with it before it goes through the "map pipe". > The next code block iterates through the res array and unless it finds a > reference? I did a perldoc on ref and see that it returns a non-empty > string if EXPR is a reference. So now I think we created an array of > hashes with the @res and map combo, is that correct? Ok, let's analyse in detail: [...] > my %actual = ( > "host1" => "164.72.119.175", > "host2" => "164.72.123.43", > "host3" => "164.72.45.98", > ); > > my %register = ( > "host1" => "164.72.119.179", > "host2" => "164.72.21.43", > "host3" => "164.72.45.98", > ); [citation removed, reformatted:] my @res = map { ( $actual{$_} eq $register{$_} ) ? $_ : [ $actual{$_}, $register{$_} ] } sort keys %register; The whole expression is to read from bottom to top; %register is the start; it is handled in 3 ways each after the other, resulting in @res. 1st, the keys are taken (keys %register). 2nd, the keys are sorted (sort) 3rd, map creates a new structure. You could image some sort of "pipe" with stations: entity:@res <- do:map <- do:sort <- do:keys <- entity:%register Note that @res does nowhere occur on the right side: It's the result; nothing is inside it before the expression on the right side of the '=' is evaluated. Now to the map part: ... <-- map { <do something> } <-- ... : It takes something at the right, mangles it, and puts it out on the left. (Note the {}-braces are part of the map; it's one of it's two syntax). Within map{}, $_ contains the sorted keys of %register; one by one is mangeld by map{}. $_ is a scalar, fed to map on the right, and map returns a scalar on the left. The scalar is either the key ( $_ ) or an arrayref [ ... ], depending of the result of the comparison, taken from after ? or after : . What the map does here (for every $_ separate) in words: "Compare the value from %actual keyed by $_ with the value from %register keyed by $_. If they are equal (means: if the IPs are equal), return the key (means: hostname); otherwise, return the two different values (means: the two different IPs) within an arrayref." I hope this helps and my english was not too confusing. Just play around with map to get the feeling. I remember that it is not easy to understand at the beginning, but if you get the idea, you won't miss it, because it allows to do complex actions in a very short way. joe [nothing new below] > foreach my $e(@res) { > unless(ref($e)) { > print "$e is ok\n"; > } > else { > print "$e differs:actual @{[$e->[0]]} <-> register @{[$e->[1]]}\n"; > } > } > > > -----Original Message----- > From: John Doe [mailto:[EMAIL PROTECTED] > Sent: Wednesday, February 01, 2006 2:45 AM > To: beginners@perl.org > Subject: Re: How to compare hashes to find matching keys with conflicting > values. > > Sorry for another mail, but there are too many typos: > > Also untested: > > > > # If no conflict, value is hostname. > > # If conflict, value is arrayref with the two different IPs > > # > > my @res = map { > > ($actual{$_} eq $register{$_}) > > ? $_ > > > > : [$actual{$_}, $register{$_}] > > > > } sort keys %register; > > > > foreach my $e (@res) { > > if (ref($e)) { > > This should read > unless (ref($e)) { > > > print "$e is ok\n"; > > } > > else { > > print "$e differs: actual @{[$e->[0]]} <-> register @{[$e->[1]]}\n"; > > } > > } > > > > I think this should give you an idea. > > To look op any perl funktion, type: > > up, function > > > perldoc -f FUNCTIONNAME > > > > The man page for operaters: > > operators > > Nice day to all :-) > > -- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > <http://learn.perl.org/> <http://learn.perl.org/first-response> -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response> -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>