I have a list of tuples, like so:
tuple_list = [(id-1,value-1),(id-2,value-2),....(id-n,value-n)]
Likewise, I have a list of objects that relates to the ids
in the list above, ie:
object_list = [<obj-3>,<obj-1>,....<obj-n>]
Note that the order in object_list
is different.
I'd like to generate a new list which is exactly like the first one above, except instead of id
, it should have the object itself in it.Ie
resulting_list = [(<obj-1>,value-1),(<obj-2>,value-2),...(<obj-n>,value-n)]
What would be the most efficient way to perform this?
I'm trying it inside two for loops currently:
resulting_list = []
for tpl in tuple_list:
for obj in object_list:
if tpl[0] == obj.id
resulting_list.append((obj,tpl[1]))
Construct a dict
where keys are are object ids and values are objects. Then iterate over tuple_list
within list comprehension and for each tuple output object from dict
and value from original list:
class Obj:
def __init__(self, id):
self.id = id
def __repr__(self):
return 'Obj({})'.format(self.id)
tuple_list = [(0, 'Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four')]
object_list = [Obj(i) for i in range(4, -1, -1)]
d = {o.id: o for o in object_list}
result = [(d[_id], val) for _id, val in tuple_list]
print(result)
Output:
[(Obj(0), 'Zero'), (Obj(1), 'One'), (Obj(2), 'Two'), (Obj(3), 'Three'), (Obj(4), 'Four')]
Time complexity of above is O(n) where as original code with nested loops is O(n^2) .
If your lists have length n
then your current algorithm does n
iterations on the outer loop, and n
iterations on each inner loop, giving a total of n*n
. You could improve that by breaking out of the inner loop as soon as you find a match. That will give an average of n*n/2
.
But it's better to do two loops each of length n
, since for large n
2n
is much smaller than n*n
. In the code below, the first loop constructs a dictionary with the object id as the key and the object itself as the value. Then the second loop can quickly find the object from its id.
obj_map = {obj.id: obj for obj in object_list}
resulting_list = [(obj_map[k], v) for k, v in tuple_list]
If it's possible that some ids in tuple_list
don't have a matching object in obj_map
and you don't want to fail with a KeyError
in that situation you can do
resulting_list = [(obj_map.get(k), v) for k, v in tuple_list]
which will supply None
for any missing objects.
Alternatively,
resulting_list = [(obj_map.get(k, default_object), v) for k, v in tuple_list]
which will supply default_object
for missing objects.
...
i = object_list.index(tpl[0]) if tpl[0] in tuple_list else -1
if i > -1:
resulting_list.append((object_list[i],tpl[1]))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.