Reputation: 207
I have a list of tuples of ID ranges such as,
[(0,2), (3,6), (7,10), (11,14), (15,21), etc.]
Plus I have multiple lists of ID integers such as,
[1, 2, 4, 11, 12, 15, 17, 20, 22, 24, ...], [2, 3, 5, 10, 13, 15, 18, 20, 23, 24, ...], etc.
The lists are not necessarily the same length.
I'm looking for a better way to return the tuples that have at least one integer in every list within its range, such as, "1" in list one and "2" in list two match tuple list[0] (range 0-2) or "11" in list one and "13" in list two match tuple list[3] (range 11-14).
I can loop through the tuples and the lists, but that is cumbersome and slow with large lists. Is there a more efficient and concise way?
Upvotes: 2
Views: 1908
Reputation: 3427
tups = [(0,2), (3,6), (7,10), (11,14), (15,21), (600,612)]
int_list = [[1, 2, 4, 11, 12, 15, 17, 20, 22, 24], [2, 3, 5, 10, 13, 15, 18, 20, 23, 24]]
for a,b in tups:
f = set(range(a,b+1))
if all(f.intersection(x) for x in int_list):
print (a,b)
Using set intersection, you should be able to come up with your answer:
(0, 2)
(3, 6)
(11, 14)
(15, 21)
All tuples whose range is represented inclusively in all lists by at least one matching integer.
Explanation: Each tuple is converted into an inclusive range. Each range in turn is checked for intersection with all possible lists in a generator. If any of the tuples have no intersection with a list, all() continues to next tuple. If a tuple has intersection with all lists all() returns true and the tuple (a,b) is returned to the user.
Upvotes: 1
Reputation: 7329
Using the bisect module we can check if numbers in the tuple range exist in a give list by seeing if the two members of the tuple would be inserted into different indexes in that list while maintaining sorted order. This assumes the lists are sorted but the tuples can be in arbitrary order.
tups=[(2,0), (3,6), (7,10), (11,14), (15,21)]
lis=[[1, 2, 4, 11, 12, 15, 17, 20, 22, 24],
[2, 3, 5, 10, 13, 15, 18, 20, 23, 24]]
from bisect import bisect
print [(x,y) for x,y in tups if all((bisect(li,x) != bisect(li,y)) or (x in li or y in li) for li in lis)]
Upvotes: 1