Given a list of multiple iterables, I want to test if all items are disjoint.
two sets are said to be disjoint if they have no element in common
Example:
iterables = ["AB", "CDE", "AF"]
all_disjoint(iterables)
# False
iterables = ["AB", "CDE", "FG"]
all_disjoint(iterables)
# True
Python sets have an isdisjoint method which works, but it is designed for testing two elements at a time. One approach is to apply this method to each pairwise group of elements:
import itertools as it
def pairwise_(iterable):
"""s -> (s0,s1), (s1,s2), (s2,s3), ..., (sn,s0)"""
# Modified: the last element wraps back to the first element.
a, b = it.tee(iterable, 2)
first = next(b, None)
b = it.chain(b, [first])
return zip(a, b)
def all_disjoint(x):
return all((set(p0).isdisjoint(set(p1))) for p0, p1 in pairwise_(x))
Here I modified the pairwise itertools recipe to attach the first element one last time. This is not quite right however as it only tests neighboring items rather than each item against all other items in the list. I would like to test all elements more elegantly, with less code. Is there a simpler way to do this?
IIUC, you can take your list of strings, combine them, and then check if the combined length is equal to the length of the set equivalent of that string or not.
You can use ''.join to join your strings and define your function:
def all_disjoint(iterables):
total = ''.join(iterables)
return len(total) == len(set(total))
Now, test:
all_disjoint(['AB', 'CDE', 'AF'])
# False
all_disjoint(['AB', 'CDE', 'FG'])
# True
Given what you said about wanting to test that each item is disjoint with all other items, I think this does what you want:
import itertools as it
def all_disjoint(x):
return all((set(p0).isdisjoint(set(p1))) for p0, p1 in it.combinations(x, 2))
iterables = ['AB', 'CDE', 'AF']
print(all_disjoint(iterables)) # -> False
iterables = ['AB', 'CDE', 'FG']
print(all_disjoint(iterables)) # -> True
# your code gives different answer on this one
# (because it doesn't check what you want)
iterables = ['AB', 'CDE', 'AH', 'FG']
print(all_disjoint(iterables)) # -> False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With