0

I have two lists like this:

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

I would now like to filter list a, to keep only the items which contain the items in list b. So the desired output would look like this:

[[1,2,3],[2,3,4]]

I have tried some nested list comprehensions, which I could think of, but could not get the desired output. Any advice is appreciated.

2
  • 2
    Can you show what you have tried already? Commented Jun 1, 2022 at 11:38
  • some things, but I was just messing around here. I find it hard to wrap my head around this: [i for i in a if i in b in i] [i for i in a if i in i in b] [[i for i in a if i in b] for ele in a] [[i for i in b] for i in a] None of these produced the desired result. Commented Jun 1, 2022 at 11:43

5 Answers 5

1

you could try something like this :

print([i for i in a if any(map(i.__contains__,b))])

>>> [[1, 2, 3], [2, 3, 4]]
Sign up to request clarification or add additional context in comments.

2 Comments

Also personally I find the use of map with __contains__ quite confusing. I would simply write any(x in i for x in b) (it's even one character shorter ^_^)
Good point, +1 , i just forgot to update it ... :)
1

I would try something like this:

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

result = [lst for lst in a if any(x in lst for x in b)]

Comments

1

A combination of list comprehension and sets would yield the wanted result. Note; I assume that repeated items and ordering is not of interest, if this is the case - a set won't work since it ignores ordering and only allows unique items.

A simple list comprehension would do, like below

filter_items = set(filter_items)
[sublist for sublist in original_list if not set(sublist).isdisjoint(filter_items)]

There's mainly one interesting part of this list comprehension, namely the if not set(sublist).isdisjoint(filter_items). Here you only keep the sublist if the set of sublist is not disjoint of the set filter_items i.e. none of the filter_items is in the sublist.

for your given example the provided answer would yield the following:

>>> a = [[1,2,3],[2,3,4],[5,6,7],[7,8,9]]
>>> b = set([1,2])
>>> [sublist for sublist in a if not set(sublist).isdisjoint(b)]
[[1, 2, 3], [2, 3, 4]]

9 Comments

Why not just set(sublist).intersection(b)? If the intersection is not empty then you want to keep the list... (set methods doesn't require a set as an argument)
You can make b a set before comprehension to avoid repeated construction and use b.isdisjoint(sublist) (isdisjoint accepts any iterable, AFAIR).
@tomerikoo because it is unnecessary work, you don't really need intersection - you want only to know whether this intersection is not empty. isdisjoint is more optimal here.
@SUTerliakov From the docs: "Return True if the set has no elements in common with other. Sets are disjoint if and only if their intersection is the empty set." I doubt there's a (critical) difference in runtime...
@tomerikoo Interesting, I'll measure when I have time. However, I suppose that isdisjoint performs short-circuit evaluation similar to any and will return False after first matching item, while intersection will check whole set anyway. It's like any(iterator) that won't exhaust iterator and will stop after first True. I really doubt that isdisjoint is implemented like not bool(intersection), it's inefficient.
|
0

Using a set approach the in can be mimic with an intersection:

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

b_as_set = set(b)

out = [l for l in a if b_as_set.intersection(l)]
# [[1, 2, 3], [2, 3, 4]]

Comments

0

I would try something like this.

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

print([lst for lst in a if any([item in b for item in lst])])

1 Comment

No need to create a list inside the any call

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.