Add index_by function to llnl.util.lang
This commit is contained in:
parent
642778b6ff
commit
4665505936
1 changed files with 58 additions and 0 deletions
|
@ -32,6 +32,64 @@
|
|||
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):
|
||||
"""Partition a list into two lists, the first containing elements
|
||||
for which the predicate evaluates to true, the second containing
|
||||
|
|
Loading…
Reference in a new issue