I am having problems with 'splitting' a larger list into several of it's combinations. Here is an example:
Let's say I have this list:
x = [['a','b'],['c','f'],['q','w','t']]
and I want to end up with
x = [['a','b'],['c','f'],['q','w'],['q','t'],['w','t']]
so essentially
['q','w','t']
becomes
['q','w'],['q','t'],['w','t']
I see how I can convert
['q','w','t']
to
[['q','w'],['q','t'],['w','t']] #notice the extra brackets
with itertools combinations, but then I am stuck with
x = [['a','b'],['c','f'],[['q','w'],['q','t'],['w','t']]] #notice the extra brackets
Which is not what I want.
How should I do this?
EDIT:
Here is the "solution", that does not give me the result that I want:
from itertools import combinations
x = [['a','b'],['c','f'],['q','w','t']]
new_x = []
for sublist in x:
if len(sublist) == 2:
new_x.append(sublist)
if len(sublist) > 2:
new_x.append([list(ele) for ele in (combinations(sublist,2))])
Thank You
I generally use a nested list comprehension to flatten a list like this:
>>> x = [['a','b'],['c','f'],['q','w','t']]
>>> [c for s in x for c in itertools.combinations(s, 2)]
[('a', 'b'), ('c', 'f'), ('q', 'w'), ('q', 't'), ('w', 't')]
Not the best way to do it but pretty clear for understanding:
from itertools import combinations
a = [['a','b'],['c','f'],['q','w','t']]
def get_new_list(x):
newList = []
for l in x:
if len(l) > 2:
newList.extend([list(sl) for sl in combinations(l, 2)])
else:
newList.append(l)
return newList
print get_new_list(a)
>>> [['a','b'],['c','f'],['q','w'],['q','t'],['w','t']]
Related
This question already has answers here:
How do I iterate through two lists in parallel?
(8 answers)
Closed 5 years ago.
I have 2 lists of the same size.
list1 = [start1,start2,start3, start4]
list2 = [end1, end2, end3, end4]
startn in list1 corresponds to endn in list2.
I want to use both the lists in a single for loop for further calculations.
Problem being: I want to use a combination of 2 elements from each list in the for loop. For example:
I want to extract start1, start3 from list1 and end1, end3 from list2 and use these 4 values in a for loop.
For a single list, to extract a combination of 2 elements, I know it's the following code:
import itertools
for a, b in itertools.combinations(mylist, 2):
But how do I extract 2 values from list1 and the same corresponding values from list2 and use in a for loop?
You can zip the two lists and then use combination to pull out the values:
list1 = ['a', 'b', 'c', 'd']
list2 = [1,2,3,4]
from itertools import combinations
for x1, x2 in combinations(zip(list1, list2), 2):
print(x1, x2)
#(('a', 1), ('b', 2))
#(('a', 1), ('c', 3))
#(('a', 1), ('d', 4))
#(('b', 2), ('c', 3))
#(('b', 2), ('d', 4))
#(('c', 3), ('d', 4))
Use zip to combine the start and end lists together into a bunch of tuples: (s1, e1), (s2, e2), etc. Then do combinations of that:
import itertools
starts = 'start1 start2 start3 start4'.split()
ends = 'end1 end2 end3 end4'.split()
se_pairs = zip(starts, ends)
for a,b in itertools.combinations(se_pairs, 2):
a_start, a_end = a
b_start, b_end = b
print("a: (", a_start, ",", a_end, ")", "b: (", b_start, ",", b_end, ")")
There's probably a more Pythonic way but try this:
from itertools import combinations
for i, j in combinations(range(4), 2):
list1_1, list1_2, list2_1, list2_2 = list1[i], list1[j], list2[i], list2[j]
Edit: on second thoughts this is the Pythonic way. I see other people have the same idea though.
for (list1_1, list1_2), (list2_1, list2_2) in combinations(zip(list1, list2), 2):
So, I need to figure out a program that when you input 2 different strings of the same length it will return NOT print the number of differences between the two strings. The order of the characters matters as well.
For example if you input ("abcdef", "aabccf")
it should return 4.
("abcdef", "accddf") should return 2.
All I have so far is:
def differencecount ( A, B):
counter = 0
str1 = list (A)
str2 = list (B)
for letter in str1:
if letter == str2:
counter = counter + 1
return counter
All this does is return 0 though so I feel like I'm missing something.
I would use
def difference(word_one, word_two):
return sum(l1 != l2 for l1, l2 in zip(word_one, word_two))
Which works like
>>> difference('abcdef', 'abcdef')
0
>>> difference('abcdef', 'abcabc')
3
You can zip the strings together and then count how many different pairs there are:
def chardifferencecounter(x, y):
return len([1 for c1, c2 in zip(x, y) if c1 != c2])
>>> chardifferencecounter('abcdef', 'aabccf')
4
>>> chardifferencecounter('abcdef', 'accddf')
2
Explanation:
Zipping the strings together produces this:
>>> s1 = 'abcdef'
>>> s2 = 'aabccf'
>>> zip(s1, s2)
[('a', 'a'), ('b', 'a'), ('c', 'b'), ('d', 'c'), ('e', 'c'), ('f', 'f')]
so it takes a character from the same position in each string and pairs them together. So you just need to count how many pairs are different. That can be done using a list comprehension to create a list with those pairs that are the same filtered out, and then get the length of that list.
Just for a different look here is a solution that doesn't use zip or enumerate:
def chardifferencecounter(x,y):
if len(x) != len(y):
raise Exception('Please enter strings of equal length')
return sum(x[i] != y[i] for i in range(len(x)))
Note that this solution also raises an exception when x and y are of different lengths, which is what you wanted in your comment.
I'm trying to write a python script that will generate random permutations of several lists without repeating
i.e. [a,b] [c,d]
a, c
b,c,
a,d
b,d
I can generate every permutation using the following, however the result is somewhat non random:
for r in itertools.product(list1, list2):
target.write("%s,%s" % (r[0], r[1])
Does anyone know a way i can implement this such that I can extract only 2 permutations, and they will be completely random but ensure that they will never be repeated?
You can use random.choice():
>>> from itertools import product
>>> import random
>>> l1 = ['a', 'b', 'c']
>>> l2 = ['d', 'e', 'f']
>>> prod = tuple(product(l1, l2))
>>>
>>> random.choice(prod)
('c', 'e')
>>> random.choice(prod)
('a', 'f')
>>> random.choice(prod)
('c', 'd')
Or simply use a nested list comprehension for creating the products:
>>> lst = [(i, j) for j in l2 for i in l1]
If you don't want to produce duplicate items you can use a set object which will create a set object from your product without an specified order then you can simply pot the items from it:
>>> prod = set(product(l1, l2))
>>>
>>> prod.pop()
('c', 'f')
>>> prod.pop()
('a', 'f')
>>> prod.pop()
('a', 'd')
Or use shuffle in order to shuffle the iterable, as #ayhan has suggested in his answer.
You can use random.shuffle then pop to make sure the results will not be repeated:
list1 = ["a", "b"]
list2 = ["c", "d"]
p = list(itertools.product(list1, list2))
random.shuffle(p)
e1 = p.pop()
e2 = p.pop()
list(itertools.product()) is not efficient as it generates and stores all of them. If you have big lists you can generate one at a time and check whether they are duplicated:
s = set()
list1 = ["a", "b"]
list2 = ["c", "d"]
while True:
r = (random.choice(list1), random.choice(list2))
if r not in s:
target.write("%s,%s" % (r[0], r[1]))
s.add(r)
break
How to write a function to rearrange a list according to the dictionary of index in python?
for example,
L=[('b',3),('a',2),('c',1)]
dict_index={'a':0,'b':1,'c':2}
I want a list of :
[2,3,1]
where 2 is from 'a',3 is from 'b' and 1 is from 'c', but rearrange only the number in L according to the dict_index
Try this (edited with simpler solution):
L=[('b',3),('a',2),('c',1)]
dict_index={'a':0,'b':1,'c':2}
# Creates a new empty list with a "slot" for each letter.
result_list = [0] * len(dict_index)
for letter, value in L:
# Assigns the value on the correct slot based on the letter.
result_list[dict_index[letter]] = value
print result_list # prints [2, 3, 1]
sorted and the .sort() method of lists take a key parameter:
>>> L=[('b',3),('a',2),('c',1)]
>>> dict_index={'a':0,'b':1,'c':2}
>>> sorted(L, key=lambda x: dict_index[x[0]])
[('a', 2), ('b', 3), ('c', 1)]
and so
>>> [x[1] for x in sorted(L, key=lambda x: dict_index[x[0]])]
[2, 3, 1]
should do it. For a more interesting example -- yours happens to match alphabetical order with the numerical order, so it's hard to see that it's really working -- we can shuffle dict_index a bit:
>>> dict_index={'a':0,'b':2,'c':1}
>>> sorted(L, key=lambda x: dict_index[x[0]])
[('a', 2), ('c', 1), ('b', 3)]
Using list comprehensions:
def index_sort(L, dict_index):
res = [(dict_index[i], j) for (i, j) in L] #Substitute in the index
res = sorted(res, key=lambda entry: entry[0]) #Sort by index
res = [j for (i, j) in res] #Just take the value
return res
I want to get all the 3 letter permutations possible from every letter in the alphabet using itertools. This comes back blank:
import itertools
def permutations(ABCDEFGHIJKLMNOPQRSTUVWXYZ, r=3):
pool = tuple(iterable)
n = len(pool)
r = n if r is None else r
for indices in product(range(n), repeat=r):
if len(set(indices)) == r:
yield tuple(pool[i] for i in indices)
What am I doing wrong?
You are a bit mixed up, that is just code explaining what permutations does. itertools is actually written in C code, the python equivalent is just given to show how it works.
>>> from itertools import permutations
>>> from string import ascii_uppercase
>>> for x in permutations(ascii_uppercase, r=3):
print x
('A', 'B', 'C')
('A', 'B', 'D')
('A', 'B', 'E')
('A', 'B', 'F')
.....
That should work fine
The code in the itertools.permutations documentation explains how the function is implemented, not how to use it. You want to do this:
perms = itertools.permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ', r=3)
You can print them all out by converting it to a list (print(list(perms))), but you can just iterate over them in a for loop if you want to do something else with them - eg,
for perm in perms:
...