Lists and Tuples - python

Let us consider
x = ['1', '2', '3', '4', '5']
y = ['a', 'b', 'c', 'd', 'e']
How do I get the required output z?
z = [('1', 'a') , ('b', '2') , ('c', '3') , ('d', '4') , ('e', '5')]

You're looking for zip:
>>> x = ['1', '2', '3', '4', '5']
>>> y = ['a', 'b', 'c', 'd', 'e']
>>> z = zip(x, y)
>>> z
[('1', 'a'), ('2', 'b'), ('3', 'c'), ('4', 'd'), ('5', 'e')]

It's called zip:
z = zip(x, y)

Related

Generate all string combinations from given character list in python

I would like to generate all possible combinations of a given character list with a given length and exclude a few combinations. For example, if I have this list:
chars = ['a', 'b', 'c', '1', '2']
Now I want to exclude character formations of more than 2characters in a row so that combinations like aaaaa or 111111 aren't possible. And I also want the output to be a given length, for example, 5 characters. Is this possible? I thought of itertools
Thanks for any help in advance.
import itertools
chars = ['a', 'b', 'c', '1', '2']
for combination in itertools.product(chars, repeat = 5):
if all(combination.count(x) < 3 for x in combination):
print (combination)
Output:
('c', '1', '1', '2', 'c')
('c', '1', '1', '2', '2')
('c', '1', '2', 'a', 'a')
('c', '1', '2', 'a', 'b')
('c', '1', '2', 'a', 'c')
('c', '1', '2', 'a', '1')
('c', '1', '2', 'a', '2')
('c', '1', '2', 'b', 'a')
('c', '1', '2', 'b', 'b')
('c', '1', '2', 'b', 'c')
('c', '1', '2', 'b', '1')
('c', '1', '2', 'b', '2')
('c', '1', '2', 'c', 'a')
('c', '1', '2', 'c', 'b')
('c', '1', '2', 'c', '1')
('c', '1', '2', 'c', '2')
('c', '1', '2', '1', 'a')
('c', '1', '2', '1', 'b')
('c', '1', '2', '1', 'c')
('c', '1', '2', '1', '2')
('c', '1', '2', '2', 'a')
('c', '1', '2', '2', 'b')
('c', '1', '2', '2', 'c')
('c', '1', '2', '2', '1')
('c', '2', 'a', 'a', 'b')
('c', '2', 'a', 'a', 'c')
('c', '2', 'a', 'a', '1')
('c', '2', 'a', 'a', '2')
('c', '2', 'a', 'b', 'a')
('c', '2', 'a', 'b', 'b')
('c', '2', 'a', 'b', 'c')
('c', '2', 'a', 'b', '1')
('c', '2', 'a', 'b', '2')
('c', '2', 'a', 'c', 'a')
('c', '2', 'a', 'c', 'b')
('c', '2', 'a', 'c', '1')
('c', '2', 'a', 'c', '2')
('c', '2', 'a', '1', 'a')
('c', '2', 'a', '1', 'b')
('c', '2', 'a', '1', 'c')
('c', '2', 'a', '1', '1')
('c', '2', 'a', '1', '2')
('c', '2', 'a', '2', 'a')
('c', '2', 'a', '2', 'b')
('c', '2', 'a', '2', 'c')
('c', '2', 'a', '2', '1')
('c', '2', 'b', 'a', 'a')
('c', '2', 'b', 'a', 'b')
('c', '2', 'b', 'a', 'c')
('c', '2', 'b', 'a', '1')
('c', '2', 'b', 'a', '2')
('c', '2', 'b', 'b', 'a')
('c', '2', 'b', 'b', 'c')
('c', '2', 'b', 'b', '1')
('c', '2', 'b', 'b', '2')
('c', '2', 'b', 'c', 'a')
('c', '2', 'b', 'c', 'b')
('c', '2', 'b', 'c', '1')
('c', '2', 'b', 'c', '2')
('c', '2', 'b', '1', 'a')
('c', '2', 'b', '1', 'b')
('c', '2', 'b', '1', 'c')
('c', '2', 'b', '1', '1')
('c', '2', 'b', '1', '2')
('c', '2', 'b', '2', 'a')
('c', '2', 'b', '2', 'b')
('c', '2', 'b', '2', 'c')
('c', '2', 'b', '2', '1')
('c', '2', 'c', 'a', 'a')
('c', '2', 'c', 'a', 'b')
('c', '2', 'c', 'a', '1')
('c', '2', 'c', 'a', '2')
('c', '2', 'c', 'b', 'a')
('c', '2', 'c', 'b', 'b')
('c', '2', 'c', 'b', '1')
('c', '2', 'c', 'b', '2')
etc...

Zip operator parameter based on loop condition

I want to increase the number of items I zip in a string based on a for loop.
So for example, this is the code
s = "abcde"
for i in range(1, len(s)):
#if i = 1, then this should be the code statement
l = zip(s, s[1:]) #list(l) = [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]
#if i = 2, then
l = zip(s, s[1:], s[2:]) #list(l) = [('a', 'b', 'c'), ('b', 'c', 'd'), ('c', 'd', 'e')]
#if i = 3, then
l = zip(s, s[1:], s[2:], s[3:]) #list(l) = [('a', 'b', 'c', 'd'), ('b', 'c', 'd', 'e')]
Observe that for any given i, there are i + 1 iterables in the zip operator.
>>> s = '123456'
>>>
>>> for n in range(1, len(s)):
print(list(zip(*[s[i:] for i in range(0,n+1)])))
[('1', '2'), ('2', '3'), ('3', '4'), ('4', '5'), ('5', '6')]
[('1', '2', '3'), ('2', '3', '4'), ('3', '4', '5'), ('4', '5', '6')]
[('1', '2', '3', '4'), ('2', '3', '4', '5'), ('3', '4', '5', '6')]
[('1', '2', '3', '4', '5'), ('2', '3', '4', '5', '6')]
[('1', '2', '3', '4', '5', '6')]
[s[i:] for i in range(0,n+1)]
Is a list comprehension that creates a list of slices of s.
For n=2 it creates the list [s[0:], s[1:], s[2:]].
It can be written as a regular for loop:
l = []
for i in range(0,n+1):
#print(i, 's[{}:]'.format(i))
l.append(s[i:])
Using the regular for loop used in your solution would be:
for n in range(1, len(s)):
#print('n:{}'.format(n), '**********')
l = []
for i in range(0, n+1):
l.append(s[i:])
#print(l)
print(list(zip(*l)))
Here is a function adapted from an itertools recipe that does something similar.
import itertools
def nwise(iterable, n=2):
"s -> (s0,s1), (s1,s2), (s2, s3), ... for n=2"
iterables = itertools.tee(iterable, n)
# advance each iterable to the appropriate starting point
for i, thing in enumerate(iterables[1:],1):
for _ in range(i):
next(thing, None)
return zip(*iterables)
For your use:
for n in range(1, len(s)):
print(list(nwise(s, n+1)))

Get every pair-wise combination of values between two lists

Let's say I have two lists;
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
I know I can get every permutation of these two lists like so:
for r in itertools.product(a, b): print (r[0] + r[1])
But what I'm looking for is every pairwise combination stored in a tuple. So, for example, some combinations would be:
[(A, 1), (B, 2), (C, 3), (D, 4)]
[(A, 1), (B, 3), (C, 2), (D, 4)]
[(A, 1), (B, 4), (C, 3), (D, 2)]
[(A, 1), (B, 3), (C, 4), (D, 2)]
[(A, 1), (B, 2), (C, 4), (D, 3)]
So it would iterate through every possible combination so that no letter has the same number value. I'm at a loss for an efficient way to do this (particularly since I need to scale this to three lists in my actual example)
We can make permutations of one of the lists (for example here the latter one), and then zip each permutation together with the first list, like:
from functools import partial
from itertools import permutations
def pairwise_comb(xs, ys):
return map(partial(zip, xs), permutations(ys))
or in case all subelements should be lists (here these are still iterables that can take a specific shape when you "materialize" these):
from functools import partial
from itertools import permutations
def pairwise_comb(xs, ys):
return map(list, map(partial(zip, xs), permutations(ys)))
For the given sample input, we obtain:
>>> for el in pairwise_comb(a, b):
... print(list(el))
...
[('A', '1'), ('B', '2'), ('C', '3'), ('D', '4')]
[('A', '1'), ('B', '2'), ('C', '4'), ('D', '3')]
[('A', '1'), ('B', '3'), ('C', '2'), ('D', '4')]
[('A', '1'), ('B', '3'), ('C', '4'), ('D', '2')]
[('A', '1'), ('B', '4'), ('C', '2'), ('D', '3')]
[('A', '1'), ('B', '4'), ('C', '3'), ('D', '2')]
[('A', '2'), ('B', '1'), ('C', '3'), ('D', '4')]
[('A', '2'), ('B', '1'), ('C', '4'), ('D', '3')]
[('A', '2'), ('B', '3'), ('C', '1'), ('D', '4')]
[('A', '2'), ('B', '3'), ('C', '4'), ('D', '1')]
[('A', '2'), ('B', '4'), ('C', '1'), ('D', '3')]
[('A', '2'), ('B', '4'), ('C', '3'), ('D', '1')]
[('A', '3'), ('B', '1'), ('C', '2'), ('D', '4')]
[('A', '3'), ('B', '1'), ('C', '4'), ('D', '2')]
[('A', '3'), ('B', '2'), ('C', '1'), ('D', '4')]
[('A', '3'), ('B', '2'), ('C', '4'), ('D', '1')]
[('A', '3'), ('B', '4'), ('C', '1'), ('D', '2')]
[('A', '3'), ('B', '4'), ('C', '2'), ('D', '1')]
[('A', '4'), ('B', '1'), ('C', '2'), ('D', '3')]
[('A', '4'), ('B', '1'), ('C', '3'), ('D', '2')]
[('A', '4'), ('B', '2'), ('C', '1'), ('D', '3')]
[('A', '4'), ('B', '2'), ('C', '3'), ('D', '1')]
[('A', '4'), ('B', '3'), ('C', '1'), ('D', '2')]
[('A', '4'), ('B', '3'), ('C', '2'), ('D', '1')]
This thus results in 24 possible ways to combine this, since the order of 'A', 'B', 'C' and 'D' remains fixed, and the 4 characters can be assigned in 4! ways, or 4! = 4×3×2×1 = 24.
It may be a lot easier than you think. What about:
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
for aperm in itertools.permutations(a):
for bperm in itertools.permutations(b):
print(list(zip(aperm, bperm)))
First outputs:
[('A', '1'), ('B', '2'), ('C', '3'), ('D', '4')]
[('A', '1'), ('B', '2'), ('C', '4'), ('D', '3')]
[('A', '1'), ('B', '3'), ('C', '2'), ('D', '4')]
[('A', '1'), ('B', '3'), ('C', '4'), ('D', '2')]
[('A', '1'), ('B', '4'), ('C', '2'), ('D', '3')]
[('A', '1'), ('B', '4'), ('C', '3'), ('D', '2')]
[('A', '2'), ('B', '1'), ('C', '3'), ('D', '4')]
[('A', '2'), ('B', '1'), ('C', '4'), ('D', '3')]
[('A', '2'), ('B', '3'), ('C', '1'), ('D', '4')]
...
(There are 576 lines printed for these two 4-element lists)
Edit: If you want to generalize this to more iterables, you could do something like:
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
gens = [itertools.permutations(lst) for lst in (a,b)]
for perms in itertools.product(*gens):
print(list(zip(*perms)))
Which outputs the same thing, but could be easily extended, e.g.
import itertools
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
c = ['W', 'X', 'Y', 'Z']
gens = [itertools.permutations(lst) for lst in (a,b,c)] # add c
for perms in itertools.product(*gens): # no change
print(list(zip(*perms))) # ''
You can use recursion with yield for a no-import solution:
a = ['A', 'B', 'C', 'D']
b = ['1', '2', '3', '4']
def combinations(d, current = []):
if len(current) == 4:
yield current
elif filter(None, d):
for i in d[0]:
_d0, _d1 = [c for c in d[0] if c != i], [c for c in d[1] if c != d[1][0]]
yield from combinations([_d0, _d1] , current+[[i, d[1][0]]])
for i in combinations([a, b]):
print(i)
Output:
[['A', '1'], ['B', '2'], ['C', '3'], ['D', '4']]
[['A', '1'], ['B', '2'], ['D', '3'], ['C', '4']]
[['A', '1'], ['C', '2'], ['B', '3'], ['D', '4']]
[['A', '1'], ['C', '2'], ['D', '3'], ['B', '4']]
[['A', '1'], ['D', '2'], ['B', '3'], ['C', '4']]
[['A', '1'], ['D', '2'], ['C', '3'], ['B', '4']]
[['B', '1'], ['A', '2'], ['C', '3'], ['D', '4']]
[['B', '1'], ['A', '2'], ['D', '3'], ['C', '4']]
[['B', '1'], ['C', '2'], ['A', '3'], ['D', '4']]
[['B', '1'], ['C', '2'], ['D', '3'], ['A', '4']]
[['B', '1'], ['D', '2'], ['A', '3'], ['C', '4']]
[['B', '1'], ['D', '2'], ['C', '3'], ['A', '4']]
[['C', '1'], ['A', '2'], ['B', '3'], ['D', '4']]
[['C', '1'], ['A', '2'], ['D', '3'], ['B', '4']]
[['C', '1'], ['B', '2'], ['A', '3'], ['D', '4']]
[['C', '1'], ['B', '2'], ['D', '3'], ['A', '4']]
[['C', '1'], ['D', '2'], ['A', '3'], ['B', '4']]
[['C', '1'], ['D', '2'], ['B', '3'], ['A', '4']]
[['D', '1'], ['A', '2'], ['B', '3'], ['C', '4']]
[['D', '1'], ['A', '2'], ['C', '3'], ['B', '4']]
[['D', '1'], ['B', '2'], ['A', '3'], ['C', '4']]
[['D', '1'], ['B', '2'], ['C', '3'], ['A', '4']]
[['D', '1'], ['C', '2'], ['A', '3'], ['B', '4']]
[['D', '1'], ['C', '2'], ['B', '3'], ['A', '4']]

appending list in python if with item from another list

I have two lists:
list1 = [('a', '1'),('b', '2'),('c', '3')
list2 = [('a', 'x'),('b', 'y'),('c', 'z')
I want to create:
list3 = [('a', '1', 'x'),('b', '2', 'y'),('c', '3', 'z')
I've tried .append, with no success:
list3 = list1.append(list2[1])
User list comprehension:
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
list3= [(list1[i][0],list1[i][1],list2[i][1]) for i in range(len(list1))]
print(list3)
Output:
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z')]
You can use zip:
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
new_result = [(a, c, d) for (a, c), (_, d) in zip(list1, list2)]
Output:
[('a', '1', 'x'), ('b', '2', 'y'), ('c', '3', 'z')]
You can use union.
list1 = [('a', '1'),('b', '2'),('c', '3')]
list2 = [('a', 'x'),('b', 'y'),('c', 'z')]
list3 = []
for i in range(len(list1)):
for j in range(len(list2)):
if(i == j):
list3.append(set(list1[i]) | set(list2[j]))
break;
Output:
[{'a', 'x', '1'}, {'y', '2', 'b'}, {'3', 'c', 'z'}]

All combinations across multiple lists

Given a multidimensional list (a list of lists) I would like to get all possible combinations of the sub lists items.
For example an input of:
my_list = [
['a', 'b'], ['1', '2'], ['#', '&']
]
Would result in:
result = [
['a'],
['b'],
['1'],
['2'],
['#'],
['&'],
['a', '1'],
['a', '2'],
['a', '#'],
['a', '&']
['b', '1'],
['b', '2'],
['b', '#'],
['b', '&'],
['a', '1', '#'],
['a', '1', '&'],
['a', '2', '#'],
['a', '2', '&'],
...]
I tried using itertools.product(*list) but that results in a combination of all items without the smaller sets of combinations. It seems that itertools.combinations, itertools.permutations, etc don't quite give what I am looking for.
Is there a quick way of doing this?
In that case you first iterate over all possible lengths. For each length you pick all possible combinations of lists, and for each of these combinations you use itertools.product:
def weird_product(*data):
for i in range(1,len(data)+1):
for subdata in itertools.combinations(data,i):
for elem in itertools.product(*subdata):
yield elem
This generates:
>>> list(weird_product(*data))
[('a',), ('b',), ('1',), ('2',), ('#',), ('&',), ('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('a', '#'), ('a', '&'), ('b', '#'), ('b', '&'), ('1', '#'), ('1', '&'), ('2', '#'), ('2', '&'), ('a', '1', '#'), ('a', '1', '&'), ('a', '2', '#'), ('a', '2', '&'), ('b', '1', '#'), ('b', '1', '&'), ('b', '2', '#'), ('b', '2', '&')]
or more elegantly formatted:
>>> list(weird_product(*data))
[('a',),
('b',),
('1',),
('2',),
('#',),
('&',),
('a', '1'),
('a', '2'),
('b', '1'),
('b', '2'),
('a', '#'),
('a', '&'),
('b', '#'),
('b', '&'),
('1', '#'),
('1', '&'),
('2', '#'),
('2', '&'),
('a', '1', '#'),
('a', '1', '&'),
('a', '2', '#'),
('a', '2', '&'),
('b', '1', '#'),
('b', '1', '&'),
('b', '2', '#'),
('b', '2', '&')]

Categories

Resources