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):
Related
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
I have a list of tuples and I want to print flattened form of this list. I don't want to transform the list, just print it without parenthesis and brackets.
input: [ ("a", 1), ("b",2), ("c", 3)]
output: a 1 b 2 c 3
Here's what I do:
l = [ ("a", 1), ("b",2), ("c", 3)]
f = lambda x: " ".join(map(str,x))
print " ".join(f(x) for x in l)
I'm interested in if anybody has a more elegant and possibly a more efficient solution,possibly without doing join, only print. Thanks in advance.
from __future__ import print_function
l = [("a", 1), ("b",2), ("c", 3)]
print(*(i for j in l for i in j))
a 1 b 2 c 3
Or using itertools.chain to flatten:
from itertools import chain
print(*chain(*l))
Using str.join() you can use a nested list comprehension:
>>> print ' '.join([str(i) if isinstance(i,int) else i for tup in A for i in tup])
a 1 b 2 c 3
And without join() still you need to loop over the the items and concatenate them, which I think join() is more pythonic way for this aim.
If you absolutely have to do this without list flattening operations like join, then this will work, but it's terrible and you should just use join:
[sys.stdout.write(str(i) + ' ' + str(j) + ' ') for (i, j) in input]
Using stdout.write because it does not automatically append a newline like print does.
That's more simple than you can imagine.
a = [ ("a", 1), ("b",2), ("c", 3)]
for i,j in a:
print(i,j,end=' ')
I have written a for loop which gives me all the values of a specific letters place in the alphabet.
For example the word hello will give me the numbers 8, 5, 12, 12 and 14. Now I want to add them to another word which is the same length for e.g abcde, which would be 1, 2, 3, 4 and 5. Now I want to add the two numbers together but keeping the individual numbers for example 8+1, 5+2, 12+3, 12+4 and 14+5.
This is the code I have so far
for letter in message:
if letter.isalpha() == True:
x = alphabet.find(letter)
for letter in newkeyword:
if letter.isalpha() == True:
y = alphabet.find(letter)
When I try adding x and y, I get a single number. Can someone help?
If you are planning to do further calculations with the numbers consider this solution which creates a list of tuples (also by using zip, as #Kashyap Maduri suggested):
messages = zip(message, newkeyword)
positions = [(alphabet.find(m), alphabet.find(n)) for m, n in messages]
sums = [(a, b, a + b, "{}+{}".format(a,b)) for a, b in positions]
Each tuple in the sums list consists of both operands, their sum and a string representation of the addition.
Then you could for example print them sorted by their sum:
for a, b, sum_ab, sum_as_str in sorted(sums, key = lambda x: x[2]):
print(sum_as_str)
Edit
when i run the program i want it to give me the answer of those sums for e.g 14+5=19 i just want the 19 part any ideas? – Shahzaib Shuz Bari
This makes it a lot easier:
messages = zip(message, newkeyword)
sums = [alphabet.find(m) + alphabet.find(n) for m, n in messages]
And you get a list of all the sums.
You are looking for zip function. It zips 2 or more iterables together. For e.g.
l1 = 'abc'
l2 = 'def'
zip(l1, l2)
# [('a', 'd'), ('b', 'e'), ('c', 'f')] in python 2.7
and
list(zip(l1, l2))
# [('a', 'd'), ('b', 'e'), ('c', 'f')] in python 3
So here is a solution for your problem:
l = list(zip(message, newkeyword))
[str(alphabet.find(x)) + '+' + str(alphabet.find(y)) for x, y in l]
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']]