Following these two SO questions:
I came to the conclusion that the solution I proposed is mature enough to be reviewed here.
The idea is to find duplicates in a dictionary such as example below, but with extended support for mixed type content (seq/mapping/scalars):
d = collections.defaultdict(set)
[d[k].add(v) for k, v in s]
Here's my solution:
import copy
import collections
def faithfulrepr(ds):
"""Returns a plain-text representation of a mixed seq/mapping/scalar
type data structure.
The datastructure is recursively ordered (ordereddict) then a
dataset representation is returned.
Args:
ds Dataset (mixed seq/mapping/scalar data structure)
Returns:
Sorted plain-text representation of the input dataset.
"""
ds = copy.deepcopy(ds)
if isinstance(ds, collections.Mapping):
res = collections.OrderedDict()
for k, v in sorted(ds.items()):
res[k] = faithfulrepr(v)
return repr(res)
if isinstance(ds, list):
for i, v in enumerate(ds):
ds[i] = faithfulrepr(v)
return repr(ds)
return repr(ds)
def tupelize_dict(ds):
"""Group identical values of a dictionary under the same key. The keys
become a tuple of all the duplicate keys.
Args:
ds: Input dictionary
Example::
ds = {23: 'foo',
25: 'bar',
28: 'foo',
30: 'bar',
33: 'foo'}
>>>tupelize_dict(ds)
{
(23,28,33): 'foo',
(25,30): 'bar'
}
"""
taxonomy = {}
binder = collections.defaultdict(list)
for key, value in ds.items():
signature = faithfulrepr(value)
taxonomy[signature] = value
binder[signature].append(key)
return {tuple(keys): taxonomy[s] for s, keys in binder.items()}
I am open for any better name for tupelize_dict
:)