0

I have a list of tuples that I want to get all the combinations for as a set and filter out certain sets based on criteria.

For example

pairs = [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
combs = []
for i in range(len(pairs)):
        intermediate = (set(list(combinations(pairs, i))))
        if ((2,3) and (2,2) and (3,2)) in intermediate:
                combs.append(intermediate)

But it doesn't detect if any of the tuples are in the set, so I tried a more basic test version.

pairs = [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
test = set(combinations(pairs,1))
if (1,1) in test:
        print("true")

This also doesn't work even though I can clearly see in my variable explorer that the set contains (1,1).

I've also tried adding an integer 1 as one of the elements in pairs and checking if 1 is in the set but that still doesn't work. I've run out of ideas and some help would be appreciated.

  • 4
    `set(combinations(pairs, 1))` returns a set of tuples of tuples, not a set of tuples (so `(1, 1)` cannot be in `test`). Note that `(1, 1) in pairs` is `True`, as is `((1, 1),) in test`. The set of tuple _pair_ combinations is `combinations(pairs, 2)`, and you can find the expected tuple pairs in that set. – crcvd Mar 18 '21 at 02:18
  • 3
    Where you have written `if ((2,3) and (2,2) and (3,2)) in intermediate`, were you not expecting Python to have to evaluate `((2,3) and (2,2) and (3,2))` first? What do you expect to be the result of that evaluation? Now, test it. Is that result `in intermediate`? – Karl Knechtel Mar 18 '21 at 02:19
  • 1
    Did you try checking what the value of `intermediate` is? What did you expect it to look like? – Karl Knechtel Mar 18 '21 at 02:19
  • Please also see https://stackoverflow.com/questions/15112125/how-to-test-multiple-variables-against-a-value . There are multiple logical issues here, to the point where I can't hope to answer the question because I can't really understand what you want. It would help if you could create an example input that is small enough for you to work out the expected answer by hand (but big enough to where the pattern can be seen); work it out by hand; and show exactly what you expect. – Karl Knechtel Mar 18 '21 at 02:22
  • 6
    also, `((2,3) and (2,2) and (3,2)) in intermediate` does not do what you seem to think. Python is not english, logical operators dont distribute like that. You would need `(2,3) in intermediate and (2,2) in intermediate and(3,2) in intermediate` – juanpa.arrivillaga Mar 18 '21 at 02:22

2 Answers2

1

Here is your test set, which does not contain (1,1) as an isolated tuple. It is a tuple inside a tuple.

{((3, 2),), ((2, 3),), ((1, 1),), ((2, 2),), ((3, 1),), ((1, 3),), ((1, 2),), ((3, 3),), ((2, 1),)}

To detect it, you can:

for combo in test:
    if (1,1) in combo:
        print("true")

#output: true
pakpe
  • 5,391
  • 2
  • 8
  • 23
1

There are two issues here...

First, it would seem like you are not testing membership at the correct depth of a nested data structure. When you call set(combinations(pairs, i)), you get a structure that is 3 levels deep: A set of tuples of tuples of ints (ints 3 containers deep).

>>> pairs = [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
>>> test = set(combinations(pairs,1))
>>> test
{((3, 2),), ((2, 3),), ((1, 1),), ((2, 2),), ((3, 1),), ((1, 3),), ((1, 2),), ((3, 3),), ((2, 1),)}

It is perfectly valid to test if a specific tuple of tuples of ints is contained within the set, but those tuples aren't automatically flattened for you to be able to test against a simple tuple of ints.

>>> ((1,1),) in test
True
>>> (1,1) in test
False

If you want to check if any tuples within the set contain a specific sub-tuple, you'll have to iterate over the set and check each top level tuple individually (hint: things like map can make this iteration a little shorter and sweeter)

for top_tuple in test:
    if (1,1) in top_tuple:
        print("found it!")

Second, is a somewhat common trap for new python programmers, which is chaining logical operators. You must think of and or in etc.. as similar to mathematical operators similar to + - * / etc.. The other important thing is how the logical operators treat things that aren't True and False. In general python treats things that are empty such as empty lists, strings, tuples, sets, etc.. as False, as well as things that are equal to 0. Basically everything else non-zero or non-empty is treated as True. Then when you run into an and, if the first value (on the left) is True-ish the return value of the and statement will be whatever is on the right. if The first value is False-ish, the return value will be that first value. When you chain them together, they get evaluated left to right.

>>> (1,1) and "cookies"
"cookies"
>>> False and "cookies"
False
>>> (2,3) and (2,2) and (3,2)
(3, 2)
Aaron
  • 10,133
  • 1
  • 24
  • 40