Reputation: 359
I would like to determine whether a given tuple is a subset of a list of other tuples.
I have a list of tuples, for examples:
list_of_fails = list([[(1,2,3)],
[(1,2,5)],
[(1,4,3)]])
I would like to determine whether a given tuple is a subset of any of these tuples, for instance the tuple
(1,2)
The result here would be yes,yes,no
I am able to do this when my tuples are list, for instance the following code will produce what i want:
list_of_fails = list([[1,2,3],
[1,2,5],
[1,4,3]])
for sublist in list_of_fails:
if (set([1, 2]).issubset(sublist) == True):
print("yes")
else: print("no")
However converting each of my embedded tuples to a list seems rather inefficient. Is there a more efficient way to check this?
Upvotes: 0
Views: 299
Reputation: 5463
You just need to go a level deeper. Using set operations is quite efficient already.
%%timeit
for sublist in list_of_fails:
for i in sublist:
if set((1, 2)).issubset(i):
print("yes")
else: print("no")
#Output:
yes
yes
no
363 µs ± 91.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
With itertools.combinations:
%%timeit
l = list(combinations(range(1,6), 2))
for sublist in list_of_fails:
for i in sublist:
for j in l:
if set(j).issubset(i):
print(j, i, "yes")
else: print(j,i, "no")
#Output:
(1, 2) (1, 2, 3) yes
(1, 3) (1, 2, 3) yes
(1, 4) (1, 2, 3) no
(1, 5) (1, 2, 3) no
(2, 3) (1, 2, 3) yes
(2, 4) (1, 2, 3) no
(2, 5) (1, 2, 3) no
(3, 4) (1, 2, 3) no
..... and so on
23.8 ms ± 1.74 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
Compact and quick with list comprehensions:
%%timeit
[print(j, i,"yes") if set(j).issubset(i) else print(j, i, "no") for sublist in list_of_fails for i in sublist for j in l]
#Output:
(1, 2) (1, 2, 3) yes
(1, 3) (1, 2, 3) yes
(1, 4) (1, 2, 3) no
(1, 5) (1, 2, 3) no
(2, 3) (1, 2, 3) yes
(2, 4) (1, 2, 3) no
(2, 5) (1, 2, 3) no
...and so on
18.3 ms ± 1.94 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
As you can see, the list comprehension solution is both compact and fastest.
Upvotes: 1
Reputation: 1098
list_of_fails = list([[(1,2,3)],
[(1,2,5)],
[(1,4,3)]])
for sublist in list_of_fails:
if set((1, 2)).issubset(sublist[0]):
print("yes")
else:
print("no")
Upvotes: 0
Reputation: 909
Converting the tuple to a list is actually not that much of a performance problem. I quickly tested this using the following code:
import random
import time
t0 = time.time()
rs = []
for i in range(10000):
r1, r2 = random.randint(0, 10), random.randint(0, 10)
t = (r1, r2)
l = list(t)
rs.append(l)
t1 = time.time()
print(t1 - t0)
In the second run I uncomment the l = list(t)
line and change rs.append(l)
to rs.append(t)
. The results I get are:
0.04108595848083496
0.037944793701171875
That's like 3ms per 10.000 list()
calls on 2-sized tuples.
I'd say your solutions is the best way to do it.
Upvotes: 0