Diego Agher Diego Agher - 18 days ago 6
Python Question

More concise way of writing a loop inside a loop in python

I have a list of objects that are a specific class within my code like so,

[object1, object2, object3, object4, object5, object6]


Namely this class has two attributes:
class.score
and
class.id


I might have objects with the same id. Eg.:

[object1.id, object2.id, object3.id, object4.id, object5.id, object6.id] = [1, 2, 3, 4, 2, 3]


But with different scores. Eg.:

[object1.score, object2.score, object3.score, object4.score, object5.score,
object6.score] = [0.25, 0.55, 0.6, 0.4, 0.30, .33]


What I want to do is to have list with no duplicates of this objects id-wise but
adding the scores. So for the previous example the output would be:

[object1.id, object2.id, object3.id, object4.id] = [1, 2, 3, 4]
[object1.score, object2.score, object3.score, object4.score] = [.25, .85, .93, .4]


I have managed to do that with two for loops:

k = 1
for object in list_of_objects:
j = 1
for object2 in list_of_objects:
if object.id == object2.id and j > k:
object.score = object.score + object2.score
list_of_objects.remove(object2)
j += 1
k += 1


But I'm looking to do it in a more python-ish, way something along the lines of:

newlist[:] = [ x for x in list_of_objects if certain_condition(x)]


Thanks.

Answer

Normally you do this using a dictionary to detect already seen objects:

seen = {}
for x in my_objects:
    if x.id in seen:
        seen[x.id].score += x.score
    else:
        seen[x.id] = x
my_objects[:] = seen.values()

Using a dictionary makes the computation O(n) instead of O(n²)