2

I have two lists A and B where B is a superset of A.

I would like boolean list of that specifies whether an element of A is equal to an element of B. The superset list B is ordered.

If have tried this:

res = [(1 for a in A if a is b) for b in B]

According to other answers this should work. But in my case it returns a list of generators.. How can I end up with just a normal list. Something like:

A = ['a', 'b', 'c', 'e']
B = ['a', 'b', 'c', 'd', 'e', 'f']
res = [1, 1, 1, 0, 1, 0]
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
Tim
  • 2,000
  • 4
  • 27
  • 45
  • Can you edit your post so I can see what it returns? – Eli Dinkelspiel Oct 05 '15 at 10:48
  • *"it returns a list of generators"* - that's exactly what you're asking for. If you want to flatten the result, ditch the parentheses. Note that you're creating a Cartesian product, though, which isn't what you say you want. – jonrsharpe Oct 05 '15 at 10:48

2 Answers2

2

The reason you get generator objects back is because you use () , hence those make generator expressions, which are not evaluated until you iterate through them.

What you really should be using if simple in operator. Example -

>>> A = ['a', 'b', 'c', 'e']
>>> B = ['a', 'b', 'c', 'd', 'e', 'f']
>>> res = [1 if x in A else 0 for x in B]
>>> res
[1, 1, 1, 0, 1, 0]

If your usecase is more complex and you have to use is operator to compare elements of A and B . Then you can use any() function to iterate through the generator expression and return True if a match is found, other False . Example -

res = [1 if any(a is b for a in A) else 0 for b in B]

Demo -

>>> A = ['a', 'b', 'c', 'e']
>>> B = ['a', 'b', 'c', 'd', 'e', 'f']
>>> res = [1 if any(a is b for a in A) else 0 for b in B]
>>> res
[1, 1, 1, 0, 1, 0]

Also, according to your question -

I would like boolean list of that specifies whether an element of A is equal to an element of B.

If what you really want is a boolean (rather than 1 or 0) , then you can simply change above examples to -

Example 1 -

res = [x in A for x in B]

Example 2 -

res = [any(a is b for a in A) for b in B]
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • I think using `any` is unnecessary. See my answer and lmk? – Eli Dinkelspiel Oct 05 '15 at 11:02
  • I don't think you answer is correct, the OP is try to check for every element in `B` , not `A` . And as I already explained, I have given answer, if A and B contain elements that can be compared with `==` , then to use `in` operator. The `any()` is only necessary, if the actual logic is more complex and depends on using `is` rather than `==` . – Anand S Kumar Oct 05 '15 at 11:06
  • This is exactly what I was searching for. Thanks the explanation. Getting 1 and 0 or True and False is the same for me. Mathematically they are exchangable anyway. – Tim Oct 05 '15 at 11:20
  • @eli_dink because OP used `is` in his example, rather than `==` . `in` operator works based on `==` not `is` . Both `==` and `is` can return different results, as `is` is identity test (test that both are exactly the same object), whereas `==` is equality test (tests that both objects are equal) . So if the OP's code is complex and depends on using `is` instead of `==` (Though I guess this would be a rare case) , using `in` operator would not work, hence you need the `any()` . – Anand S Kumar Oct 05 '15 at 11:33
0

I think what you're looking for is the intersection of the two sets, right?

Here's the intersection of the two sets (which I highly recommend you come up with better names for next time):

A = [1, 2, 3, 5, 7, 10, 12, 9]

B = [2, 6, 7]

print [x if x in B else None for x in A]

You need the "else" in there or it doesn't work.

And to solve your problem literally:

 res = [True if x in A else False for x in B]

I recommend you check this answer out: if/else in Python's list comprehension?

Community
  • 1
  • 1
Eli Dinkelspiel
  • 769
  • 1
  • 6
  • 15