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

I have put together a script to compare user input with a db and want to extract the bits of the input which do not match the db contents

This is very convoluted and I feel is crying out for a hash but I'm not sure how to create the hash or what to do with it once I've got it!!

Having put this together I feel sure that if a kindly monk would show me a more efficient way then it would be really useful to me in terms of improving my skills

Thanks

#comma delimited user input @words = split(/,/, $words); #copy of array for later @words2 = @words; open FH, "$data" or die "Can't open $data: $!"; flock (FH, 1) or die "Can't lock $data for reading: $!"; my @all = <FH>; close FH; #iterate through user input comparing with db while (@words) { my $item = shift (@words); $count++; foreach my $line (@all) { ($one,$two,undef,$four,$spare_1,$spare_2) = split "\t",$line; chomp; if ($item eq "$four") { push (@matched, $item); push (@counted, $count); last; } } } #iterate through @counted applying undef to matched items in copy of u +ser input array while (@counted) { my $item = shift (@counted); $words2[$item -1] = undef; } #remove undef items from user input leaving only unmatched items. foreach my $item (@words2) { unless ($item eq "") { push (@uniq, $item); } } #@matched contains only matched items #@uniq contains only unmatched items

Replies are listed 'Best First'.
Re: extracting non matched items from an array - the hard way!
by bobn (Chaplain) on Jul 12, 2003 at 21:32 UTC
    Yer right, you want to use hashes:
    # UNTESTED # after creating @words and @all for ( @all ) # iterate through @all, setting $_ to each in turn { my $four = ( split("\t", $_) )[3]; # split each line on \t, extract +4th field $seen{$four}++; # add to hash } # %seen hash has keys equal to the fourth field in # all the lines in @all @matched = grep { exists $seen{$_} } @words; @uniq = grep { not exists $seen{$_} } @words; # the preceding 2 lines could also have been: for ( @words ) { if ( exists $seen{$_} ) { push @matched, $_; } else { push @uniq, $_; } } # which has the advantage of iterating over @words only once.


    --Bob Niederman, http://bob-n.com
      Many thanks, bob. The way you've set the hash on a single iteration of @all is just stunning. As I hoped there is much learnt (and to learn from this). I appreciate your explanation.