Related
How to generate tuples corresponding such that the
points =
points = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2,
4), (3, 4), (4, 2), (3, 3), (2, 4), (5, 3), (7, 4), (8, 4)]
I want to generate multiple lists of tuples where the number of in between the tuples inside of the list (hops) corresponds to the iterate number of the loops
hops = 3
for i in range(hops):
# statement i = 1 [(0, 1), (0, 2)] one hop between these tuples
i = 2 [(0, 1), (1, 2), (2, 3)] 2 hops between these tuples
i = 3 [(2, 1), (1, 7), (7, 8),(8, 10)] 3 hops between these tuples
I have a list as follows:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
Now, what I want is every element of this list is compared with all the other elements and if that element is the subset of the elements it is compared with, it should be popped. For example, [(1, 1)] is the subset of [(1, 1), (1, 2)] then [(1, 1)] should be popped from the list. Similarly, [(1, 1), (1, 2)] is the subset of [(1, 1), (1, 2), (1, 3)] then it should be popped also.
And in this case, we get the output as follows:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
I tried searching for all the possible answers but none was aimed at this particular case.
So far I have tried the following method but of little use:
for i, e in enumerate(mylist):
mylist[i] = tuple(e)
mylist = list(set(mylist))
You need to remove any list from mylist where all the tuples in the list are present in another list in mylist. This is most easily done by assigning to a new list:
newlist = []
for i, lst in enumerate(mylist):
if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:]):
newlist.append(lst)
Or as a list comprehension:
newlist = [lst for i, lst in enumerate(mylist) if not any(all(t in l for t in lst) for l in mylist[:i] + mylist[i+1:])]
In both cases, for your sample data the output is:
[
[(1, 1), (1, 2), (1, 3)],
[(1, 1), (1, 2), (1, 4)]
]
For larger lists this might become slow, in which case you can speed it up by first mapping the entries in mylist to sets:
mylist=[[(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)], [(1, 1)]]
mylist=list(map(set, (tuple(l) for l in mylist)))
newlist = [list(lst) for i, lst in enumerate(mylist) if not any(lst.issubset(l) for l in mylist[:i] + mylist[i+1:])]
You can use frozenset.issubset and do the comparaison like this example:
Thanks to #Nick suggestion, this is a more elaborated example:
mylist=[[(1, 1)], [(1, 1), (1, 2)], [(1, 1), (1, 2), (1, 3)], [(1, 1),
(1, 2), (1, 4)]]
out = []
for k, elm in enumerate(mylist):
for elm2 in mylist[:k] + mylist[k + 1:]:
if frozenset(elm).issubset(elm2):
break
else:
out.append(elm)
print(out)
Output:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
Neither solutions from #Nick and #ChihebNexus are efficient.
The answer from #Nick requires a time complexity of O(m ^ 2 x n ^ 2), while #ChihebNexus's answer requires a time complexity of O(m ^ 2 x n), where m is the length of the input list and n is the average length of the sub-lists.
For an approach that requires just a time complexity of O(m x n), you can create a dict that maps each tuple item to a set of the sub-lists the item appears in, keeping in mind that these sub-lists need to be converted to tuples first to become hashable and be added to a set:
mapping = {}
for lst in mylist:
for item in lst:
mapping.setdefault(item, set()).add(tuple(lst))
so that with your sample input, mapping becomes:
{(1, 1): {((1, 1),),
((1, 1), (1, 2)),
((1, 1), (1, 2), (1, 3)),
((1, 1), (1, 2), (1, 4))},
(1, 2): {((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2)), ((1, 1), (1, 2), (1, 4))},
(1, 3): {((1, 1), (1, 2), (1, 3))},
(1, 4): {((1, 1), (1, 2), (1, 4))}}
And then with the mappings of items to their belonging sub-lists built, we can then iterate through the sub-lists again, and take the intersection of the sets of sub-lists that the items in the current sub-list map to, in order to find the sub-lists that contain all the items in the current sub-list. If there are more than one of such qualifying sub-lists, it means that the current sub-list is a subset of the other qualifying sub-lists, and that we can remove the current sub-list from the result by removing it from all the sets its items map to. The sub-lists that survive this process will be the ones we want in the output, which we can obtain by aggregating the sets with a union operation:
for lst in mylist:
if len(set.intersection(*map(mapping.get, lst))) > 1:
t = tuple(lst)
for item in lst:
mapping[item].remove(t)
print(set.union(*mapping.values()))
This outputs:
{((1, 1), (1, 2), (1, 3)), ((1, 1), (1, 2), (1, 4))}
You can convert it to a list of lists if you really want the exact data types in the question:
list(map(list, set.union(*mapping.values())))
which returns:
[[(1, 1), (1, 2), (1, 3)], [(1, 1), (1, 2), (1, 4)]]
I have a generator of tuples and I need to delete tuples containing same elements. I need this output for iterating.
Input = ((1, 1), (1, 2), (1, 3), (3, 1), (3, 2), (3, 3))
Output= ((1, 1), (1, 2), (1, 3))
Order of output doesn't matter.
I have checked this question but it is about lists: Delete duplicate tuples with same elements in nested list Python
I use generators to achieve fastest results as the data is very large.
You can normalize the data by sorting it, then add it to a set to remove duplicates
>>> Input = ((1, 1), (1, 2), (1, 3), (3, 1), (3, 2), (3, 3))
>>> Output = set(tuple(sorted(t)) for t in Input)
>>> Output
{(1, 2), (1, 3), (2, 3), (1, 1), (3, 3)}
How would I implement the following using python? I've tried using lambda expressions and a few other methods, but I'm not getting the desired results. Basically, I should receive a set of relations that satisfy the check. I.E they have to be divisible by each other, so {(1,1), (1,2), (1,3),...(6,6)}.
Here's the actual question:
In Python, set a variable say S = {1,2,3,4,5,6}; then do as follows: "List all the ordered pairs in the relation R = {(a,b) : a divides b} on the set {1,2,3,4,5,6}."
you can do it by list comprehension -
S = [1,2,3,4,5,6]
result = [ (x,y) for x in S for y in S if y%x==0]
You can use itertools.product within a list comprehension,and as you want they be divisible by each other you can use the condition i%j==0 or j%i==0 :
>>> from itertools import product
>>> [(i,j) for i,j in product(S,repeat=2) if i%j==0 or j%i==0]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 4), (2, 6), (3, 1), (3, 3), (3, 6), (4, 1), (4, 2), (4, 4), (5, 1), (5, 5), (6, 1), (6, 2), (6, 3), (6, 6)]
[{(a,b) : a/b} for a in S for b in S]
For example:
alist=[[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2), (2, 1), (2, 0), (1, 0), (3, 0)],
[(0, 2), (0, 3), (1, 3)],
[(0, 4), (1, 4), (2, 4), (0, 5), (0, 6), (1, 6), (2, 6), (3, 6)],
[(1, 5)],
[(2, 3), (3, 3), (3, 4), (3, 5), (2, 5), (3, 2), (3, 1)]]
for i in dlist:
print(len(i))
print(max(len(i))) #this gives me error
output:
5
9
3
8
1
7
I wanted to print out 9 as my output from the above list. How am I able to print the result?
Somewhat more terse
len(max(alist,key=len))
If you can be sure your nesting is only one level (that is, a list of lists):
print max(len(sublist) for sublist in alist)
functional style using map:
print max(map(len, alist))
If you want the actual index of the longest sublist:
max(((i,l) for i,l in enumerate(alist)), key=lambda t: len(t[1]))[0]
Or, as stated in comments:
max(enumerate(alist), key=lambda t: len(t[1]))[0]