3

While trying to workout list comprehension , I got stuck with desired value repeated.

I have 2 lists: L1, L2. Result required is list of items from L2 if these items are smaller than/ equal to, at least one of the items in L1.

L1=[10,20,30,40,50]
L2=[3,11,51]
L3=[d2 for d2 in L2 for d1 in l1 if d2<=d1]

L3 is returned as [3, 3, 3, 3, 3, 11, 11, 11, 11]

Answer contains valid items, but are repeated. I know using set(), we can get rid of repetitions but may be I am using list-comprehension in a wrong way. Any clarification would be appreciated.

Loops to achieve the desired result would be:

L3=[]
for d2 in L2:
    for d1 in L1:
        if d2<=d1:
            L3.append(d2)

3 Answers 3

5

As you can see from your expansion into loops, the inner loop runs over every element in L1, so the d2 element will get appended once for every time there's a bigger element in L2.

You could use a set() (equivalently, { } brackets as HepaKKes suggests) to get rid of repetitions, but this is inefficient -- you're still creating the unneeded intermediate results. It will be O(n^2) time.

You're selecting items based on whether they're <= than any item in L1. This is the same as asking whether they're <= max(L1). So the following:

L3 = [e for e in L2 if e < max(L1)]

will achieve the same result. If you save the value of L1 ahead of time

L1_max = max(L1)
L3 = [e for e in L2 if e < L1_max]

then this solution is O(n).

Sign up to request clarification or add additional context in comments.

Comments

2

What you wrote goes through two nested for-loops, and whenever the condition d2<=d1 is true, that value is appended. So we're seeing both 3 and 11 added for each value in L2 that they're less than.

Instead, you'll want a stricter condition for adding d2 to L3, so that your comprehension can be of the form L3 = [d2 for d2 in L2 if (x)], where x is equivalent to "d2 is less than some value in L1". There are a few ways to do that, but I found the following to work:

L3 = [d2 for d2 in L2 if (filter(lambda d1: d2<=d1, L1))]

3 Comments

filter returns a list. I think you want to use any, as in: if any(d2 <= d1 for d1 in L1). Map would also work.
ah, yup. filter works here because any non-empty list evaluates to True, but any would be cleaner.
oh, it does work. ha! (yeah, I would still use any).
1

If the task is to write a single list comprehension, I would go for something like this:

In [22]: [x for x in L2 if any([y >= x for y in L1])]
Out[22]: [3, 11]

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.