hash differences

Discussion in 'Perl Misc' started by int, Sep 15, 2005.

  1. int

    int Guest

    i have 2 hashes, %newer and %older. %newer is an update of the
    data in %older. i would like to know:
    1) which key, value pairs are in %newer but not %older
    2) which key, value pairs are in %older but not %newer
    3) which keys have different values in %older and %newer
    4) which values have different keys in %older and %newer

    wrote some code, it is messy, it is over 30 lines long lots
    of foreach, if, else, blocks and it seems to have a problem
    with case 4). looking for a perl idiomatic solution.

    any suggestions appreciated.
     
    int, Sep 15, 2005
    #1
    1. Advertising

  2. int wrote:
    > i have 2 hashes, %newer and %older. %newer is an update of the
    > data in %older. i would like to know:
    > 1) which key, value pairs are in %newer but not %older
    > 2) which key, value pairs are in %older but not %newer
    > 3) which keys have different values in %older and %newer
    > 4) which values have different keys in %older and %newer
    >
    > wrote some code, it is messy, it is over 30 lines long lots
    > of foreach, if, else, blocks and it seems to have a problem
    > with case 4). looking for a perl idiomatic solution.
    >
    > any suggestions appreciated.


    I suggest using Ruby:

    older = {
    'aa', 11,
    'bb', 22,
    'cc', 33,
    'dd', 44,
    'ee', 55,
    'ff', 66 }

    newer = older.dup
    newer['bb'] = 55 ; newer['ee'] = 22 ; newer['gg'] = 77

    p ( newer.to_a - older.to_a ).sort
    p ( older.to_a - newer.to_a ).sort
    p (older.keys & newer.keys).reject{ |x| newer[x]==older[x] }.sort
    p (older.values & newer.values).reject{ |x|
    newer.index(x)==older.index(x)}.sort

    -----------------------------------------------------------------

    Output:

    [["bb", 55], ["ee", 22], ["gg", 77]]
    [["bb", 22], ["ee", 55]]
    ["bb", "ee"]
    [22, 55]
     
    William James, Sep 15, 2005
    #2
    1. Advertising

  3. int

    Anno Siegel Guest

    int <> wrote in comp.lang.perl.misc:
    > i have 2 hashes, %newer and %older. %newer is an update of the
    > data in %older. i would like to know:
    > 1) which key, value pairs are in %newer but not %older
    > 2) which key, value pairs are in %older but not %newer
    > 3) which keys have different values in %older and %newer
    > 4) which values have different keys in %older and %newer
    >
    > wrote some code, it is messy, it is over 30 lines long lots
    > of foreach, if, else, blocks and it seems to have a problem
    > with case 4). looking for a perl idiomatic solution.
    >
    > any suggestions appreciated.


    Study the faq "How do I compute the difference of two arrays? ..."
    (perldoc -q difference). It demonstrates the standard method of
    doing this in Perl.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Sep 15, 2005
    #3
  4. int <> wrote:
    > i have 2 hashes, %newer and %older. %newer is an update of the
    > data in %older. i would like to know:
    > 1) which key, value pairs are in %newer but not %older
    > 2) which key, value pairs are in %older but not %newer
    > 3) which keys have different values in %older and %newer
    > 4) which values have different keys in %older and %newer


    > wrote some code, it is messy, it is over 30 lines long lots
    > of foreach, if, else, blocks and it seems to have a problem
    > with case 4). looking for a perl idiomatic solution.


    Well, case 4 is very different. The easiest way to do that is to build
    a reverse hash, where each value is put into another hash as its key,
    and the original key is the value. When you get to the second hash, you
    know if it was in the first and what the key was. In addition, the
    question is very difficult to answer if the values are not unique within
    each of the original hashes.

    I don't know if it's idiomatic or not, but here's how I'd do the first
    3.

    foreach $key (keys %hash1)
    if exists $hash2{$key}
    [ check case 3 and see if values are same or different ]
    delete $hash2{$key}
    else
    [ record $key as existing only in hash1 ]

    [all remaining keys in hash2 are unique to hash2]

    --
    Darren Dunham
    Senior Technical Consultant TAOS http://www.taos.com/
    Got some Dr Pepper? San Francisco, CA bay area
    < This line left intentionally blank to confuse you. >
     
    Darren Dunham, Sep 15, 2005
    #4
  5. int

    int Guest

    thanks for the suggestions. i agree, it's a difficult question
    and it's not addressed in the faq. there is no guarantee
    of uniqueness between hashes.

    for example if

    $older{aa}="alpha";
    $older{bb}="beta";
    $older{cc}="gamma";

    then newer could be

    1)
    $newer{aa}="alpha";
    $newer{bb}="beta";
    $newer{cc}="gamma";
    $newer{dd}="delta";

    2)
    $newer{aa}="alpha";
    $newer{bb}="beta";

    3)
    $newer{aa}="alpha";
    $newer{bb}="beta";
    $newer{cc}="omega";

    4)
    $newer{aa}="alpha";
    $newer{bb}="beta";
    $newer{dd}="gamma";

    5) some combination like
    $newer{aa}="alpha";
    $newer{cc}="omega";
    $newer{dd}="gamma";
    $newer{tt}="theta";

    the ruby solution is ideal but unfortunately I'm trapped in
    perl for this. here is pseudo code for my solution. it has
    problems and it's too long. there has to be a better "perl"
    way.

    foreach my $k (keys %newer) {
    if (! exists $older{$k}) {
    # this is a new key
    if (! map (/$newer{$k}/, keys reverse %older) ) {
    # value is new too
    print "new pair: $k, $newer{$k}\n";
    }
    else {
    # new value for a pre-existing key
    print "new key: $k, for value $older{$k}\n";
    }
    }
    }
    foreach my $k (keys %older) {
    if (! exists $newer{$k}) {
    # the key is gone
    if (! map (/$older{$k}/, keys reverse %newer) ) {
    # both key and value are gone
    print "key, value pair removed: $k, $older{$k}\n";
    }
    else {
    # new value for a pre-existing key should be here
    # but alas, it isn't. why isn't it symmetric?
    # need yet another foreach loop here
    }
    }
    }



    int
     
    int, Sep 15, 2005
    #5
  6. int wrote:
    > i have 2 hashes, %newer and %older. %newer is an update of the
    > data in %older. i would like to know:
    > 1) which key, value pairs are in %newer but not %older
    > 2) which key, value pairs are in %older but not %newer
    > 3) which keys have different values in %older and %newer
    > 4) which values have different keys in %older and %newer


    <snip and jump to later post>

    > thanks for the suggestions. i agree, it's a difficult question
    > and it's not addressed in the faq. there is no guarantee
    > of uniqueness between hashes.


    <snip>

    >
    > the ruby solution is ideal but unfortunately I'm trapped in
    > perl for this. here is pseudo code for my solution. it has
    > problems and it's too long. there has to be a better "perl"
    > way.


    Have you considered checking out Set::Hash and Set::Array? Requirements
    1 and 2 are simple using Set::Hash (OK - they are fairly simple using
    other methods), and you should be able to work something out for 3 and 4
    using the provided set operations and building a reverse mapping as
    suggested by Darren.

    Mark
     
    Mark Clements, Sep 15, 2005
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Red Orchid
    Replies:
    3
    Views:
    1,090
  2. Home_Job_opportunity
    Replies:
    0
    Views:
    524
    Home_Job_opportunity
    Jan 8, 2009
  3. Home_Job_opportunity
    Replies:
    0
    Views:
    611
    Home_Job_opportunity
    Jan 14, 2009
  4. rp
    Replies:
    1
    Views:
    581
    red floyd
    Nov 10, 2011
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    670
    David A. Black
    Jul 2, 2008
Loading...

Share This Page