Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intermediate variable in a list comprehension for simultaneous filtering and transformation

I have a list of vectors (in Python) that I want to normalize, while at the same time removing the vectors that originally had small norms.

The input list is, e.g.

a = [(1,1),(1,2),(2,2),(3,4)]

And I need the output to be (x*n, y*n) with n = (x**2+y**2)**-0.5

If I just needed the norms, for example, that would be easy with a list comprehension:

an = [ (x**2+y**2)**0.5 for x,y in a ]

It would be also easy to store just a normalized x, too, for example, but what I want is to have this temporary variable "n", to use in two calculations, and then throw it away.

I can't just use a lambda function too because I also need the n to filter the list. So what is the best way?

Right now I am using this nested list comprehension here (with an expression in the inner list):

a = [(1,1),(1,2),(2,2),(3,4)]

[(x*n,y*n) for (n,x,y) in (( (x**2.+y**2.)**-0.5 ,x,y) for x,y in a) if n < 0.4]

# Out[14]: 
# [(0.70710678118654757, 0.70710678118654757),
#  (0.60000000000000009, 0.80000000000000004)]

The inner list generates tuples with an extra value (n), and then I use these values for the calculations and filtering. Is this really the best way? Are there any terrible inefficiencies I should be aware of?

like image 408
dividebyzero Avatar asked Nov 04 '10 14:11

dividebyzero


People also ask

Can you assign variables in list comprehension Python?

You can't assign a variable in a comprehension, but you can use a nested generator expression, which does what I think you want (without a lambda function). Show activity on this post. You can't do that. Assignment is always a statement in Python; list comprehensions can only contain expressions.

Which is faster filter or list comprehension?

1 Answer. Actually, list comprehension is much clearer and faster than filter+lambda, but you can use whichever you find easier.

What does a comprehension filtering predicate do?

Python list comprehension predicate. A predicate is a function that returns boolean value. If the condition is too complex, we can put it into a predicate. The example filters out all vowels from a sentence.

What is list comprehension method in Python?

List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list. Example: Based on a list of fruits, you want a new list, containing only the fruits with the letter "a" in the name.


2 Answers

Is this really the best way?

Well, it does work efficiently and if you really, really want to write oneliners then it's the best you can do.

On the other hand, a simple 4 line function would do the same much clearer:

def normfilter(vecs, min_norm):
    for x,y in vecs:
        n = (x**2.+y**2.)**-0.5
        if min_norm < n:
            yield (x*n,y*n)

normalized = list(normfilter(vectors, 0.4))

Btw, there is a bug in your code or description - you say you filter out short vectors but your code does the opposite :p

like image 198
Jochen Ritzel Avatar answered Sep 29 '22 11:09

Jochen Ritzel


Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), it's possible to use a local variable within a list comprehension in order to avoid calling multiple times the same expression:

In our case, we can name the evaluation of (x**2.+y**2.)**-.5 as a variable n while using the result of the expression to filter the list if n is inferior than 0.4; and thus re-use n to produce the mapped value:

# vectors = [(1, 1), (1, 2), (2, 2), (3, 4)]
[(x*n, y*n) for x, y in vectors if (n := (x**2.+y**2.)**-.5) < .4]
# [(0.7071067811865476, 0.7071067811865476), (0.6000000000000001, 0.8)]
like image 29
Xavier Guihot Avatar answered Sep 29 '22 09:09

Xavier Guihot