Add index_by function to llnl.util.lang
This commit is contained in:
parent
642778b6ff
commit
4665505936
@ -32,6 +32,64 @@
|
|||||||
ignore_modules = [r'^\.#', '~$']
|
ignore_modules = [r'^\.#', '~$']
|
||||||
|
|
||||||
|
|
||||||
|
def index_by(objects, *funcs):
|
||||||
|
"""Create a hierarchy of dictionaries by splitting the supplied
|
||||||
|
set of objects on unique values of the supplied functions.
|
||||||
|
Values are used as keys. For example, suppose you have four
|
||||||
|
objects with attributes that look like this:
|
||||||
|
|
||||||
|
a = Spec(name="boost", compiler="gcc", arch="bgqos_0")
|
||||||
|
b = Spec(name="mrnet", compiler="intel", arch="chaos_5_x86_64_ib")
|
||||||
|
c = Spec(name="libelf", compiler="xlc", arch="bgqos_0")
|
||||||
|
d = Spec(name="libdwarf", compiler="intel", arch="chaos_5_x86_64_ib")
|
||||||
|
|
||||||
|
list_of_specs = [a,b,c,d]
|
||||||
|
index1 = index_by(list_of_specs, lambda s: s.arch, lambda s: s.compiler)
|
||||||
|
index2 = index_by(list_of_specs, lambda s: s.compiler)
|
||||||
|
|
||||||
|
``index1'' now has two levels of dicts, with lists at the
|
||||||
|
leaves, like this:
|
||||||
|
|
||||||
|
{ 'bgqos_0' : { 'gcc' : [a], 'xlc' : [c] },
|
||||||
|
'chaos_5_x86_64_ib' : { 'intel' : [b, d] }
|
||||||
|
}
|
||||||
|
|
||||||
|
And ``index2'' is a single level dictionary of lists that looks
|
||||||
|
like this:
|
||||||
|
|
||||||
|
{ 'gcc' : [a],
|
||||||
|
'intel' : [b,d],
|
||||||
|
'xlc' : [c]
|
||||||
|
}
|
||||||
|
|
||||||
|
If any elemnts in funcs is a string, it is treated as the name
|
||||||
|
of an attribute, and acts like getattr(object, name). So
|
||||||
|
shorthand for the above two indexes would be:
|
||||||
|
|
||||||
|
index1 = index_by(list_of_specs, 'arch', 'compiler')
|
||||||
|
index2 = index_by(list_of_specs, 'compiler')
|
||||||
|
"""
|
||||||
|
if not funcs:
|
||||||
|
return objects
|
||||||
|
|
||||||
|
f = funcs[0]
|
||||||
|
if isinstance(f, basestring):
|
||||||
|
f = lambda x: getattr(x, funcs[0])
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for o in objects:
|
||||||
|
key = f(o)
|
||||||
|
if key not in result:
|
||||||
|
result[key] = [o]
|
||||||
|
else:
|
||||||
|
result[key].append(o)
|
||||||
|
|
||||||
|
for key, objects in result.items():
|
||||||
|
result[key] = index_by(objects, *funcs[1:])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def partition_list(elements, predicate):
|
def partition_list(elements, predicate):
|
||||||
"""Partition a list into two lists, the first containing elements
|
"""Partition a list into two lists, the first containing elements
|
||||||
for which the predicate evaluates to true, the second containing
|
for which the predicate evaluates to true, the second containing
|
||||||
|
Loading…
Reference in New Issue
Block a user