Skip to content

Instantly share code, notes, and snippets.

@jnothman
Created May 20, 2013 08:54
Show Gist options
  • Save jnothman/5611142 to your computer and use it in GitHub Desktop.
Save jnothman/5611142 to your computer and use it in GitHub Desktop.
from collections import defaultdict
from six import iteritems
def group_params(items, key_name=lambda x: True):
"""bin by sub-dicts where values are compared by id if not hashable
>>> a = ('boo', 6)
>>> b = ('boo', 6)
>>> id(a) == id(b)
False
>>> import numpy
>>> c = numpy.array([1, 2, 3])
>>> items = [{'p': a, 'q': 1}, {'p': b, 'q': 2}, {'p': c, 'q': 3}, {'p': c, 'q': 4}]
>>> groups = list(group_params(items, lambda x: x == "p"))
>>> len(groups)
2
>>> groups
>>> sorted([[x['q'] for x in gitems] for g, gitems in groups if g['p'] == a][0])
[1, 2]
>>> sorted([[x['q'] for x in gitems] for g, gitems in groups if g['p'] is c][0])
[3, 4]
"""
# can reduce work if input is sorted tuples rather than dict
groups = defaultdict(list)
canonical = {} # maps hashable x to a canonical instance of x
id_to_obj = {}
for params in items:
group = []
for k, v in iteritems(params):
if key_name(k):
try:
v_id = id(canonical.setdefault(v, v))
except TypeError:
v_id = id(v)
id_to_obj[v_id] = v
group.append((k, v_id))
groups[tuple(sorted(group))].append(params)
return [({k: id_to_obj[v_id] for k, v_id in group}, group_items)
for group, group_items in iteritems(groups)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment