6

For example, I have two lists of the same length:

a = [[1,2],[2,2],[3,3],[4,2],[5,6]]
b = [1,2,2,3,1]

I want to have a function such that

func(a,b,1) = [[1,2],[5,6]]
func(a,b,2) = [[2,2],[3,3]]
func(b,b,2) = [2,2]

What the function does is return a list of a's elements, whose corresponding elements of the same index in list b equal to the third argument.

In Matlab I will do something as easy as a(b==1), a(b==2), b(b==2). What is the most efficient way to achieve this in Python?

5
  • 5
    It is not very clear what you want this function/filter to do Commented Jun 21, 2012 at 20:28
  • It would be useful to actually explain what you want, rather than expect us to deduce it from input/output. Also, what have you tried? SO is not a place to get code written for you. Commented Jun 21, 2012 at 20:29
  • 2
    Ah I get it, it's: Return the values in the first argument in the positions of the elements in the second argument that are equal the third argument. Commented Jun 21, 2012 at 20:33
  • You need to explain what you want func to do? You can't assume we know matlab nor can you assume we can deduce what func does from input/output. Commented Jun 21, 2012 at 20:39
  • Sorry guys I assumed the Matlab expression explained it all. Thanks for the heads up. Commented Jun 22, 2012 at 15:24

4 Answers 4

11

If you want very Matlab-like functionality, you could use numpy:

>>> import numpy
>>> a = [[1,2],[2,2],[3,3],[4,2],[5,6]]
>>> b = [1,2,2,3,1]
>>> a = numpy.array(a)
>>> b = numpy.array(b)
>>> a[b==1]
array([[1, 2],
       [5, 6]])
>>> a[b==2]
array([[2, 2],
       [3, 3]])
>>> b[b==2]
array([2, 2])

Failing that, I'd probably simply use a list comprehension:

>>> [i for i,j in zip(a,b) if j == 1]
[[1, 2], [5, 6]]
>>> [i for i,j in zip(a,b) if j == 2]
[[2, 2], [3, 3]]
>>> [i for i,j in zip(b,b) if j == 2]
[2, 2]

It'd be trivial to wrap this in a function:

>>> def func(a,b,x):
...     return [i for i,j in zip(a,b) if j == x]
... 
>>> func(a,b,2)
[[2, 2], [3, 3]]
>>> 
Sign up to request clarification or add additional context in comments.

Comments

6

I would use itertools.compress() along with a generator expression to do this:

def func(a, b, c):
    return itertools.compress(a, (x == c for x in b))

Note that this will return a generator. If you need a list, wrap it in a list() call.

>>> import itertools
>>> def func(a, b, c):
...     return list(itertools.compress(a, (x == c for x in b)))
... 
>>> a = [[1,2],[2,2],[3,3],[4,2],[5,6]]
>>> b = [1,2,2,3,1]
>>> func(a, b, 1)
[[1, 2], [5, 6]]
>>> func(a, b, 2)
[[2, 2], [3, 3]]
>>> func(b, b, 2)
[2, 2]

It's also worth noting this should be nice and fast - itertools is designed to be a fast module.

Comments

4

This first finds the indices where b equals the target values ([i for i, x in enumerate(b) if x==c]), then uses those indices to get the elements you want out of a:

def func(a,b,c):
    return [a[j] for j in [i for i, x in enumerate(b) if x==c]]

>>> func(a,b,1)
[[1, 2], [5, 6]]
>>> func(a,b,2)
[[2, 2], [3, 3]]
>>> func(b,b,2)
[2, 2]

3 Comments

Well done for working that out based on what he gave - it was cryptic at best.
@Lattyware: The description might not have been clear, but I thought the Matlab code was.
@Junuxx no need of two for loops, see my answer.
1
def func(a,b,n):
   return [a[i] for i,x in enumerate(b) if x==n]

a = [[1,2],[2,2],[3,3],[4,2],[5,6]]
b = [1,2,2,3,1]
print(func(a,b,1)) #[[1, 2], [5, 6]]
print(func(a,b,2)) #[[2, 2], [3, 3]]
print(func(b,b,2)) #[2, 2]

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.