On 5/11/10 Tue  May 11, 2010  1:52 PM, "Harry Putnam" <rea...@newsguy.com>
scribbled:

> Shawn H Corey <shawnhco...@gmail.com> writes:
> 
>> Harry Putnam wrote:
>>> But, is there an easier way?
>> 
>> Invert both hashes and find the keys in both inverses.
> 
> Shawn, hoping to pester you once more about this topic.

It is not fair to single out Shawn for help. Just post your question and
hope for a response.

> %d1h is made up like this
> 
>    this is key              this is value
>   $File::Find::name      =     $_

The use of the equal sign '=' in the above makes it look like you are
assigning a value to $File::Find::name. It is better to stick to Perl
syntax:

        $d1h{$File::Find::name} = $_;

for example:

        $d1h{'./dir1/sub/fname'} = 'fname';

> So cutting to the chase, I try to take advantage of your inversion
> code.  It seems to work well, but I'm not confident enough to know
> if there are possible hidden gotchas someone with more experience
> might see right off the bat.
>  
> -------        ---------       ---=---       ---------      --------
> Some selective output first:
> 
>   [...]
> 
>   d1         ./dir1/etc/images/gnus/exit-summ.xpm
>   d2    (1)  ./dir2/etc/images/gnus/exit-summ.xpm
> 
>   d1         ./dir1/etc/images/gnus/reply.xpm
>   d2    (1)  ./dir2/etc/images/mail/reply.xpm
>   d2    (2)  ./dir2/etc/images/gnus/reply.xpm
> 
>   d1         ./dir1/etc/images/gnus/README
>   d2    (1)  ./dir2/src/m/README
>   d2    (2)  ./dir2/etc/e/README
>         [...] 
>   d2    (47)  ./dir2/doc/lispintro/README
> 
>   d1         ./dir1/lisp/gnus-util.el
>   d2    (1)  ./dir2/lisp/gnus/gnus-util.el

You can use the Unix file command (if you are on Unix) to find the files
with a certain name:

    find dir1 -name README

etc. to check the results of your program.

Your program below looks fine. I see no obvious defects. You can generate
the inverted hashes in the find routines (see below). You can use the
inverted hashes only (see below).

> #!/usr/local/bin/perl
> 
> use strict;
> use warnings;
> use File::Find;
> #use diagnostics;
> 
> my %d1h;
> my %d2h;
> my $d1tag = 'd1';
> my $d2tag = 'd2';
> 
> ## Make sure we are  feed two directory names
> ( my ( $d1, $d2 ) = @ARGV ) == 2
>     or die "\nUsage: $0 ./dir1 ./dir2\n";
> 
>   ## Make sure incoming directory names exist
>   for ($d1, $d2 ){
>      ( -d ) or die "<$_> cannot be found on the file system";
>   }
> 
>   ## Build the hashs
> 

my( %inv_d1h, %inv_d2h );

>   find sub {
>       return unless -f;
>       $d1h{ $File::Find::name } = $_;

        push( @{$inv_d1h{$_}}, $File::Find::name );

>     },$d1;
> 
>   find sub {
>       return unless -f;
>       $d2h{ $File::Find::name } = $_;

        push( @{$inv_d2h{$_}}, $File::Find::name );

>     },$d2;
> 
> ## Invert 1 hash and it needs to be the second one on cmd line
> my %inv_d2h = invert( \%d2h );
> 
> sub invert {
>    my $h = shift @_;
>    my %inv = ();
> 
>    while( my ( $k, $v ) = each %{ $h } ){
>      push @{ $inv{$v} }, $k;
>    }
>    return %inv;
> }
> 
> ## Could have used `values' of %d1h here for $value (values %d1h)
> ## and avoided things like `...@{ $inv_d2h{ $d1h{ $key } } }',
> ## which would then be     `...@{ $inv_d2h{ $value } }'  but would
> ## not then have such ready access to the `keys' which are
> ## needed here too, and will be needed later on (not shown here)
> ## for now we just print to show how it works.
> 
> foreach my $key ( keys %d1h ){
>   if(exists $inv_d2h{ $d1h{ $key } }){
>      print "  $d1tag         $key\n";
> 
>        ## separate counter to keep (my) confusion down
>        my $matchcnt = 0;
>        for ( @{ $inv_d2h{ $d1h{ $key } } } ) {
>            print "  $d2tag    (" . ++$matchcnt .")  $_\n";
>        }
>        print "\n";
>   }              
> }
>

Using only "inverted" hashes (untested):

  for my $file ( sort keys %inv_d1h ) {
    if( exists $inv_d2h{$file} ) {
      print "Duplicate file names found: ", scalar @{$inv_d1h{$file}},
       " in $d1 and ", scalar @{$inv_d2h{$file}}, " in $d2\n";
      print "\n$d1:\n    ", join("\n    ",@{inv_d1h{$file}}), "\n";
      print "\n$d2:\n    ", join("\n    ",@{inv_d2h{$file}}), "\n";
    }
  }



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to