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

I've got a situation where there are a hundred items, either true or false.

I've got the old list of which ones are true or false, and I've edited it using a web form, probably removing some from the "true" list and adding others to it.

Having submitted the form, what's the best way to reset the list correctly?

I did it like this:

I made a hash of 100 entries all set to zero, then did a foreach on the list of old items, and set the right values to 1.

Then I made a hash of 100 entries all set to zero and did a foreach loop on the list of new items, setting the right values to 1.

Then I went through the hash keys like this:

foreach $entry(@a){ if ($oldhash{$entry}==1 && $newhash{$entry}==0){ # push it into an array of deletions to be made } elsif($newhash{$entry}==1 && $oldhash{$entry}==0){ # ditto array of additions to be made } }

I've been staring at this code for a while and I can't figure out if that's a dumb way to do it or not, but it feels kind of dumb.

Is there a smarter way?
--

Edit: chipmunk 2002-02-24

Replies are listed 'Best First'.
Re: comparing two hashes
by chipmunk (Parson) on Feb 24, 2002 at 06:24 UTC
    What you're really trying to do is subtract one set from another set. Hashes are the right tool, but this can be done with slices instead of loops.
    # find old values that are not in new values my %deletions; @deletions{@oldvalues} = (); delete @deletions{@newvalues}; my @deletions = keys %deletions; # find new values that are not in old values my %additions @additions{@newvalues} = (); delete @additions{@oldvalues}; my @additions = keys %additions;

    Update: fixed hash names.

      chipmunk is right that hashes are the right tool to use here. However, there are some instances when hashes are not usable:

      • When you need to preserve the order of the data
      • If you have duplicate keys.

      I have had quite a lot of success with Algorithm::Diff. See also Re: Comparing Elements of Two Arrays.


      That looks very much smarter and I'm sure it works, but can you (or anyone) please explain it a little more?

      What is

      @deletions{@oldvalues} = ();
      doing? I didn't know you could create hashes that way!

      Also, what's "%tmp"? --

        Thats something called a hash slice.This is used to refer to (and/or operate on) multiple hash elements at the same time.
        hth
Re: comparing two hashes
by Cody Pendant (Prior) on Feb 25, 2002 at 00:13 UTC
    Is it bad form to come back and answer my question? I looked at "comparing two arrays" in categorised Q and A, and dumbed it down a little to this:
    # List pair which has one old item to be deleted, # and one new item to be added: @oldlist = ( 1,3,5,7,9 ); @newlist = ( 3,5,7,9,11 ); foreach $item(@oldlist){ $old{$item}=1; } foreach $item(@newlist){ $new{$item}=1; } # Find the stuff that's on both lists: my @bothlists = grep {defined $new{$_}} @oldlist; print "Stuff on both lists: @bothlists\n"; # Find the stuff that's on the old but not the new list: my @deletions = grep {!defined $new{$_}} @oldlist; print "Stuff on old but not on new (needs deleting): @deletions\n"; # Find the stuff that's on the new but not the old list: my @additions = grep {!defined $old{$_}} @newlist; print "Stuff on new but not on old (needs adding) @additions\n";