4

I have 3 lists in Python.

list_a = [10., 20., 30., 12.]
list_b = [30., 20., 60., 12.]
list_c = [10., 80., 90., 12.]

I want to drop those elements in list_b and list_c where values in list_a are <= 15. Therefore results become:

list_b = [20., 60.]
list_c = [80., 90.]

Is there a way to do this without for loops? (list comprehensions are ok)

4
  • 1
    Without loops? I don't think so. also shouldn't list_b be [30.,20.,60.,] ? Commented Jan 2, 2017 at 9:17
  • You're not using Numpy, are you? One can do this easily with Numpy arrays. Commented Jan 2, 2017 at 9:20
  • @DavidZ I am using numpy, is there a compact way to do this there? Commented Jan 2, 2017 at 9:23
  • @snakecharmerb returning new lists is ok Commented Jan 2, 2017 at 9:24

6 Answers 6

8

If you are using numpy as you said you are, in comments, you can simply create a boolean index from a and mask elements in b and c:

import numpy as np

list_a = np.array([10., 20., 30., 12.])
list_b = np.array([30., 20., 60., 12.])
list_c = np.array([10., 80., 90., 12.])

list_b = list_b[list_a>15]
list_c = list_c[list_a>15]

print list_a
print list_b
print list_c

Output:

[ 10.  20.  30.  12.]
[ 20.  60.]
[ 80.  90.]

You can convert the lists_b and list_c to Python list type by .tolist() method.

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

Comments

7

You can use the little known itertools.compress class to do this. See Filter list using Boolean index arrays

>>> import itertools
>>> list_a = [10., 20., 30., 12.]
>>> list_b = [30., 20., 60., 12.]
>>> list_c = [10., 80., 90., 12.]
>>> bool_list = [item > 15 for item in list_a]
>>> bool_list
[False, True, True, False]
>>> list_b = list(itertools.compress(list_b, bool_list))
>>> list_b
[20.0, 60.0]
>>> list_c = list(itertools.compress(list_c, bool_list))
>>> list_c
[80.0, 90.0]

Comments

5

You may write a one-liner to filter the list via using zip() as:

list_b, list_c = zip(*[(b, c) for a, b, c in zip(list_a, list_b, list_c) if a>15])

The final values hold by list_b and list_c will be:

>>> list_b
(20.0, 60.0)
>>> list_c
(80.0, 90.0)

Comments

2

Can you use list comprehensions?

You could do it like this:

list_a = [10., 20., 30., 12.]
list_b = [30., 20., 60., 12.]
list_c = [10., 80., 90., 12.]
list_b = [ el for (i, el) in enumerate(list_b) if (list_a[i] > 15) ]
list_c = [ el for (i, el) in enumerate(list_c) if (list_a[i] > 15) ]

Snipper was written here, I haven't tested it, but you see the general idea.

I assumed that all lists are the same length. If list_a is shorter and you want to drop elements that are on the missing positions, you can do it like this:

list_b = [ el for (i, el) in enumerate(list_b) if (i<len(list_a) and list_a[i] > 15) ]

and if you want to keep them, just reverse the sign and boolean operator:

list_b = [ el for (i, el) in enumerate(list_b) if (i>=len(list_a) or list_a[i] > 15) ]

Comments

1

You can zip() like below:

>>> list_a = [10., 20., 30., 12.]
>>> list_b = [30., 20., 60., 12.]
>>> list_c = [10., 80., 90., 12.]
>>>
>>> [j for i,j in zip(list_a, list_b) if i >= 15]
[20.0, 60.0]
>>>
>>> [j for i,j in zip(list_a, list_c) if i >= 15]
[80.0, 90.0]

Comments

0
list_a = [10., 20., 30., 12.]
list_b = [30., 20., 60., 12.]
list_c = [10., 80., 90., 12.]
drop = [i for i,v in enumerate(list_a) if v <=15]
b = [v for i,v in enumerate(list_b) if not i in drop]
c = [v for i,v in enumerate(list_c) if not i in drop]

1 Comment

This isn't a complete answer. Please add an explanation too, for future reference

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.