If i have two lists:
a = [1,2,1,2,4] and b = [1,2,4]
how do i get
a - b = [1,2,4]
such that one element from b removes only one element from a if that element is present in a.
You can use itertools.zip_longest to zip the lists with different length then use a list comprehension :
>>> from itertools import zip_longest
>>> [i for i,j in izip_longest(a,b) if i!=j]
[1, 2, 4]
Demo:
>>> list(izip_longest(a,b))
[(1, 1), (2, 2), (1, 4), (2, None), (4, None)]
a = [1,2,1,2,4]
b = [1,2,4]
c= set(a) & set(b)
d=list(c)
The answer is just a little modification to this topic's answer:
Find non-common elements in lists
and since you cannot iterate a set object:
https://www.daniweb.com/software-development/python/threads/462906/typeerror-set-object-does-not-support-indexing
Related
Input: 1 2 3 4
Output: (1,2)(3,4)
(1,3)(2,4)
(1,4)(2,3)
I have been able to come up with a solution for the problem but it is efficient. It needs to be optimized.
comb = combinations(Arr,int(n/2))
l = []
for i in comb:
l.append(i)
final_comb = combinations(l,int(n/2))
for i in final_comb:
if is_unique(n,i):
print(i)
def is_unique(n,tup):
k = []
for i in tup:
for j in i:
k.append(j)
if len(set(k)) == n:
return True
return False
The output must be combinations of tuples such that they all have the numbers given as input
Use itertools
from itertools import combinations
list(combinations([1, 2, 3, 4], 2))
>>> [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
I have to merge all the tuples containing atleast one element of each other.
tups=[(1,2),(2,3),(8,9),(4,5),(15,12),(9,6),(7,8),(3,11),(1,15)]
first tuple (1,2) should be merged with (2,3),(3,11),(1,15),(15,12) since each of these tuples contains similar items of the preceding tuple. so the final ouput should be
lst1 = [1,2,3,11,12,15]
lst2=[6,7,8,9] since (8,9),(9,6) and (7,8) have matching elements
My code so far:
finlst=[]
for items in range(len(tups)):
for resid in range(len(tups)):
if(tups[items] != tups[resid] ):
if(tups[items][0]==tups[resid][0] or tups[items][0]==tups[resid][1]):
finlst.append(list(set(tups[items]+tups[resid])))
You could do it like this, using sets that are expanded with matching tuples:
tups = [(1, 2), (2, 3), (8, 9), (4, 5), (15, 12), (9, 6), (7, 8), (3, 11), (1, 15)]
groups = []
for t in tups:
for group in groups:
# find a group that has at least one element in common with the tuple
if any(x in group for x in t):
# extend the group with the items from the tuple
group.update(t)
# break from the group-loop as we don’t need to search any further
break
else:
# otherwise (if the group-loop ended without being cancelled with `break`)
# create a new group from the tuple
groups.append(set(t))
# output
for group in groups:
print(group)
{1, 2, 3, 11, 15}
{8, 9, 6, 7}
{4, 5}
{12, 15}
Since this solution iterates the original tuple list once and in order, this will not work for inputs where the connections are not directly visible. For that, we could use the following solution instead which uses fixed-point iteration to combine the groups for as long as that still works:
tups = [(1, 2), (3, 4), (1, 4)]
import itertools
groups = [set(t) for t in tups]
while True:
for a, b in itertools.combinations(groups, 2):
# if the groups can be merged
if len(a & b):
# construct new groups list
groups = [g for g in groups if g != a and g != b]
groups.append(a | b)
# break the for loop and restart
break
else:
# the for loop ended naturally, so no overlapping groups were found
break
I found the solution, it's more of graph theory problem related to connectivity, Connectivity-Graph Theory
We can use NetworkX for this, it's pretty much guaranteed to be correct:
def uniqueGroup(groups):
# grp=[]
# for group in groups:
# grp.append(list(group))
# l=groups
import networkx
from networkx.algorithms.components.connected import connected_components
def to_graph(groups):
G = networkx.Graph()
for part in groups:
# each sublist is a bunch of nodes
G.add_nodes_from(part)
# it also imlies a number of edges:
G.add_edges_from(to_edges(part))
return G
def to_edges(groups):
"""
treat `l` as a Graph and returns it's edges
to_edges(['a','b','c','d']) -> [(a,b), (b,c),(c,d)]
"""
it = iter(groups)
last = next(it)
for current in it:
yield last, current
last = current
G = to_graph(groups)
return connected_components(G)
Output:
tups = [(1, 2),(3,4),(1,4)]
uniqueGroup(tups)
{1, 2, 3, 4}
Here are my few lines of code
import numpy as np
X = ([1,2,3], [2,4,5], [5,6,7])
y = ([2], [4], [5])
dist= np.random.RandomState(1)
r = dist.permutation(len(y))
Let's say
r= array([0, 2, 1])
Is there a way to permute the elements of X and y so that X and y elements are re-ordered according to indexes in r array i.e. y becomes ([2], [5], [1]) and X becomes ([1,2,3], [5,6,7], [2,4,5]) ? I didn't find out the answer in python doc. Thanks
You can use comprehension with zip:
[i for _, i in sorted(zip(r, X])]
EDIT
When you zip this happens:
zip(r, X)
#((0, [1,2,3]), (2, [2,4,5]), (1, [5,6,7]))
Then you use sorted() this happens:
sorted(zip(r, X])
((0, [1,2,3]), (1, [5,6,7]), (2, [2,4,5]))
When you take only second element from ziped and sorted you get this:
([1,2,3], [5,6,7], [2,4,5])
Is there any other argument than key, for example: value?
Arguments of sort and sorted
Both sort and sorted have three keyword arguments: cmp, key and reverse.
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
Using key and reverse is preferred, because they work much faster than an equivalent cmp.
key should be a function which takes an item and returns a value to compare and sort by. reverse allows to reverse sort order.
Using key argument
You can use operator.itemgetter as a key argument to sort by second, third etc. item in a tuple.
Example
>>> from operator import itemgetter
>>> a = range(5)
>>> b = a[::-1]
>>> c = map(lambda x: chr(((x+3)%5)+97), a)
>>> sequence = zip(a,b,c)
# sort by first item in a tuple
>>> sorted(sequence, key = itemgetter(0))
[(0, 4, 'd'), (1, 3, 'e'), (2, 2, 'a'), (3, 1, 'b'), (4, 0, 'c')]
# sort by second item in a tuple
>>> sorted(sequence, key = itemgetter(1))
[(4, 0, 'c'), (3, 1, 'b'), (2, 2, 'a'), (1, 3, 'e'), (0, 4, 'd')]
# sort by third item in a tuple
>>> sorted(sequence, key = itemgetter(2))
[(2, 2, 'a'), (3, 1, 'b'), (4, 0, 'c'), (0, 4, 'd'), (1, 3, 'e')]
Explanation
Sequences can contain any objects, not even comparable, but if we can define a function which produces something we can compare for each of the items, we can pass this function in key argument to sort or sorted.
itemgetter, in particular, creates such a function that fetches the given item from its operand. An example from its documentation:
After, f=itemgetter(2), the call f(r) returns r[2].
Mini-benchmark, key vs cmp
Just out of curiosity, key and cmp performance compared, smaller is better:
>>> from timeit import Timer
>>> Timer(stmt="sorted(xs,key=itemgetter(1))",setup="from operator import itemgetter;xs=range(100);xs=zip(xs,xs);").timeit(300000)
6.7079150676727295
>>> Timer(stmt="sorted(xs,key=lambda x:x[1])",setup="xs=range(100);xs=zip(xs,xs);").timeit(300000)
11.609490871429443
>>> Timer(stmt="sorted(xs,cmp=lambda a,b: cmp(a[1],b[1]))",setup="xs=range(100);xs=zip(xs,xs);").timeit(300000)
22.335839986801147
So, sorting with key seems to be at least twice as fast as sorting with cmp. Using itemgetter instead of lambda x: x[1] makes sort even faster.
Besides key=, the sort method of lists in Python 2.x could alternatively take a cmp= argument (not a good idea, it's been removed in Python 3); with either or none of these two, you can always pass reverse=True to have the sort go downwards (instead of upwards as is the default, and which you can also request explicitly with reverse=False if you're really keen to do that for some reason). I have no idea what that value argument you're mentioning is supposed to do.
Yes, it takes other arguments, but no value.
>>> print list.sort.__doc__
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1
What would a value argument even mean?
I can't figure out how to get permutations to return the actual permutation and not
I tried a lot of different things to no avail. The code I used was from itertools import permutations and then permutations([1,2,3]). Thanks!
This may not be answering your question (it appears to be missing the part after 'and not'), but from your code, what you are likely seeing is the repr of the itertools.permutations iterator. You can iterate through this object just as you would a normal list in order to access all of the items. If you want to convert it to a list, you can wrap it in list:
>>> from itertools import permutations
>>> permutations([1, 2, 3])
<itertools.permutations object at 0x1e67890>
>>> list(permutations([1, 2, 3]))
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
However as mentioned above, the iterator can be iterated over just like you would a normal list (the benefit of returning an iterator is that the entire sequence is not loaded into memory right away - it is instead loaded 'as needed'):
>>> for perm in permutations([1, 2, 3]):
... print(perm)
...
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
itertools.permutations is a generator, which means you have to retrieve results from it by using it like this:
for permutation in itertools.permutations([1,2,3]):
do_stuff_with(permutation)
or alternatively put all of them in a list:
list(itertools.permutations([1,2,3]))
or, less conveniently:
generator = itertools.permutations([1,2,3])
generator.__next__()
from itertools import permutations
#iteration
for p in permutations([1,2,3]):
print(p)
This should work perfectly.