Given two lists in python one with strings and one with objects, how do you map them?
I have a list of strings
string_list = ["key_val_1", "key_val_2", "key_val_3", "key_val_4", ...]
and a list with objects
object_list = [object_1, object_2, object_3,...]
Every object object_i
has an attribute key
.
I want to sort the objects in obje开发者_开发技巧ct_list
by the order of string_list
.
I could do something like
new_list = []
for key in string_list:
for object in object_list:
if object.key == key:
new_list.append(object)
but there must be a more pythonic way, then this brute force one. :-) How would you solve this?
First, create a dictionary mapping object keys to objects:
d = dict((x.key, x) for x in object_list)
Next create the sorted list using a list comprehension:
new_list = [d[key] for key in string_list]
Map each key to its desired precedence:
key_precedence = dict((x, n) for n, x in enumerate(string_list))
Then sort by precedence:
object_list.sort(key=lambda x: key_precedence[x.key])
To handle keys that might not be in string_list:
default = -1 # put "unknown" in front
default = sys.maxint # put "unknown" in back
object_list.sort(key=lambda x: key_precedence.get(x.key, default))
If string_list is short (e.g. 10 or fewer items), you can simplify:
object_list.sort(key=lambda x: string_list.index(x.key))
# But it's more cumbersome to handle defaults this way.
However, this is prohibitive for larger lengths of string_list.
You can use the cmp argument of the sort() method:
object_list.sort(cmp=lambda x,y: cmp(string_list.index(x.key),
string_list.index(y.key)))
or use sorted() to avoid the in-place substitution:
sorted(object_list, cmp=lambda x,y: cmp(string_list.index(x.key),
string_list.index(y.key)))
精彩评论