hash differences

I

int

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.
 
W

William James

int said:
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]
 
A

Anno Siegel

int said:
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
 
D

Darren Dunham

int said:
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]
 
I

int

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
 
M

Mark Clements

int said:
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

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.

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top