http://qs321.pair.com?node_id=66898

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

Basically I want to list all ids from @data2 that aren't in @data. Here's my attempt.

foreach (@data) { ($id,$var2,$var3,$var4,$var5) = split( /,/, $_); $id = grep { m/$id$/ } @data2; print "This $id was not found.\n"; }

Replies are listed 'Best First'.
Re: grepping
by indigo (Scribe) on Mar 25, 2001 at 01:33 UTC
    No grep required.
    my %h; @h{@data2} = (); delete @h{@data}; my @ids = keys %h;
Re: grepping
by dws (Chancellor) on Mar 25, 2001 at 01:02 UTC
    { my %data; @data{@data} = 1; # turn @data into a lookup hash foreach ( @data2 ) { print "This $_ was not found.\n" if not exists $data{$_} } }

    Update: An aside with MeowChow has convinced me that     @data{@data} = undef;  # turn @data into a lookup hash is less misleading. As with the "= 1" form above, only the value for the first key is set, and all remaining values are set to undef. Since we're just using the hash as a way to trade time for space in detecting the presense of keys, values don't matter. But the originally was slightly misleading nonetheless.

      Replacing the hash slice assignment with the following:
      undef @data{@data};
      is considerably faster, though somewhat obscure. Also, your slice assignment doesn't do quite what you mean it to do (it sets only the first key's value to 1, and the rest to undef).
         MeowChow                                   
                     s aamecha.s a..a\u$&owag.print
      Okay, question...@data has three variables $id, $name, $ref and @data2 has 5 variables $id, $name, $ref, $type, $owner.

      { my %data; undef @data{@data}; foreach ( @data2 ) { print "This $_ was not found.\n" if not exists $data{$_} } }

      This code is matching all 5 variables in @data2 to all 3 variables in @data, thus returning every row in @data2. For a test I took out all but 1 variable from each row in each array and it returned the results I needed. How can I use this code to handle multiple variables or values? And what if I wanted to lookup $name instead of $id.

      Thanks!
        I think you misundertand the relationship between variables and arrays. Arrays hold values; they do not hold variables.

        Consider:

        my $id = 47; my @data = ( $id );
        @data now holds the value 47, and knows nothing whatsoever about where that value came from.

        The script you've asked for (and gotten) mere tells which values appear in one array and not the other.

Re: grepping
by MeowChow (Vicar) on Mar 25, 2001 at 13:52 UTC
    As it turns out, your particular problem is somewhat more complicated than we had all assumed. Here's one way to solve it:
    use strict; # this simply gives us some sample data, just like # you would have gotten from doing @data = <FILE> my @data = split $/, <<EOF; 1,comp1,type1 2,comp2,type2 3,comp3,type3 EOF my @data2 = split $/, <<EOF; 1,comp1,type1,doc1,ref1 2,comp2,type2,doc2,ref2 3,comp3,type3,doc3,ref3 4,comp4,type4,doc4,ref4 5,comp5,type5,doc5,ref5 EOF # end of sample-data # figure out how many columns there are in @data my $num_cols = () = $data[0] =~ /,/g; # create hash-keys based on the number of columns my %d2keys; $d2keys{join ',', (split /,/)[0..$num_cols]} = $_ for @data2; # delete duplicates delete @d2keys{@data}; # and we're left with the ones that differ... my @diff = values %d2keys; # proof that it worked :) print $_,$/ for @diff;
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: grepping
by chipmunk (Parson) on Mar 27, 2001 at 22:30 UTC