0

I am doing some stuff in python, but I am not that used to it yet.

This is what I want the code to do (pseudocode):

if x in list or y in list but not x and y:
    #do-stuff

the first part is correct (if x in list or y in list) but I don't know what to write after that. The but not x and ypart.

5
  • What do you actually want to do? Commented Jul 5, 2014 at 12:02
  • I am iterating through a set of lists. I want it to only do calculations if the list contains X or Y but not both. Commented Jul 5, 2014 at 12:03
  • 7
    use xor: (x in list) ^ (y in list) Commented Jul 5, 2014 at 12:04
  • do the if and check first, Commented Jul 5, 2014 at 12:04
  • 1
    If the primary operation you want to perform on list is membership tests, you should use a set instead. Commented Jul 5, 2014 at 12:11

4 Answers 4

4

I'd probably go for using a set here instead...

if len({x, y}.intersection(your_list)) == 1:
    # do something

This has the advantage that it only needs to iterate once over your_list.

Example:

examples = [
    [1, 2, 3, 4, 5],
    [2, 3, 4, 5, 6],
    [100, 101, 102, 103, 104]
]

for example in examples:
    overlap = {1, 5}.intersection(example)
    print 'overlap is', overlap, 'with a length of', len(overlap)

# overlap is set([1, 5]) with a length of 2
# overlap is set([5]) with a length of 1
# overlap is set([]) with a length of 0
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks. But behzad.nouri's answer solved it for me. I used xor: "(x in list) ^ (y in list)"
@user3685412 indeed... they both work... but (x in list) ^ (y in list) has to scan list twice to compute the either/or
Oh okay. That's nice. I'll definitely use yours then. The list is pretty big :)
@user3685412 note: you can't use this approach if x and y happen to be unhashable...
On the other hand, your solution needs to create a temporary set. It's a classic time vs. space tradeoff, but with no change in complexity.
|
1

With "but" spelled and and a pair of parentheses, you can use:

x_in_list = x in list
y_in_list = y in list
if (x_in_list or y_in_list) and not (x_in_list and y_in_list):
    ...

Or, as suggested by behzad.nouri, use xor:

if (x in list) ^ (y in list):
    ...

This is shorter, but possibly less understandable to a non-CS-savvy reader.

Comments

1

Exclusive or means "one or the other, but not both" and maps perfectly in what you want to do:

if (x in list) ^ (y in list):
    ...

looks a bit weird because normally xor is only used for bitwise operations, but here works because Python will implicitly convert True and False to 1 and 0, making the operator work as expected in an if.

Note however that the parenthesis are necessary because the xor operator ^ has an higher precedence than in (it's most often used for bitwise math, so this choice is reasonable).

1 Comment

Note that True and False aren't converted to 1 and 0, in a very real sense they already are 1 and 0.
1

Inspired by Jon Clements's centi-upvoted answer,

items, it = {x, y}, (i in items for i in lst)
print(any(it) and not any(it))

This short-circuit version is better, in the negative cases.

it is an iterator of the original list, and we check if any of it is in items, if yes we check if all the other items are not in items.

Note: This works only if the items are unique in lst

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.