2

Suppose i have the following for loop

L=[]
for e in C:
    t=0
    for r in D:
        if r[0]==e:
            t=t+r[2]
    L.append((e,t))

To give some more information e is a list, r is a tuple of size 3. I also want each element of L to contain a tuple.

How do i write the following in a list comprehension? I'm unsure as there are variable assignments in the for loop. I'd really appreciate any help! Thanks!!

3 Answers 3

8

work it up in reverse.

What is the data to append to L ? a tuple. What is this tuple made of? e (we have it) and the sum of some terms given a condition.

So without testing I can write:

L = [(e,sum(r[2] for r in D if r[0]==e)) for e in C]
Sign up to request clarification or add additional context in comments.

4 Comments

There has to be a better answer that does not traverse D len(C) times but just once. If we just want to translate OP's loop to a comprehension 1-1, it does not get better than this.
yes, you may be right, but without further test data, it's difficult to see that. it would probably involve generating a dict of some sort to save the inner loop.
anyway I'm keeping this Q&A for my future training sessions :) a good example of complex loop turned into ... a complex list comprehension :)
@Ev.Kounis to avoid re-traversing one has to build the index of D first, so that filtering turns into trivial key lookup in a dict.
3
L = [
    (
        e,
        (sum(r[2] for r in D if r[0]==e))
    )
    for e in C
]

3 Comments

There's something going wrong with the parentheses around sum
not the downvoter, but sum(r[2]) this can't be correct
Oops, fixed. The answer above got it right first time :)
3

This solution might be more complicated and not a simple list-comprehension but it is also more efficient (O(n) instead of O(n2)). The reason is that we no longer have go through the entire list D for every item e we get from C but only once. As a result, the benefits of this approach scale with increasing size of D or C.

from operator import itemgetter
from itertools import groupby

D = [["A", 0], ["B", 1], ["C", 0], ["D", 2], ["A", 2]]
D.sort(key=itemgetter(0))

glo = {k: sum(f[1] for f in g) for k, g in groupby(D, key=itemgetter(0))}

L = [(e, glo[e]) for e in C]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.