Python zip list of tuples [duplicate] - python

This question already has answers here:
Transpose/Unzip Function (inverse of zip)?
(14 answers)
Closed 1 year ago.
How can I zip a list of tuples in Python?
# From
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
# To
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Just use zip and list comprehension.
>>> tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [list(i) for i in zip(*tuples)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Or,
>>> tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
>>> [[*i] for i in zip(*tuples)]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]

If you are okay with using numpy then
import numpy as np
l=[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
[tuple(i) for i in (np.array(l).transpose())]

Related

Possible combination of a nested list in python

If I have a list of lists and want to find all the possible combination from each different indices, how could I do that?
For example:
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I want to find
all_possibility = [[1, 5, 9], [1, 8, 6], [4, 2, 9], [4, 8, 3], [7, 2, 6], [7, 5, 3]]
where
[1,5,9]: 1 is 1st element of [1, 2, 3], 5 is 2nd element of [4, 5, 6], 9 is 3rd element of [7, 8, 9].
[1,8,6]: 1 is 1st element of [1, 2, 3], 8 is 2nd element of [7, 8, 9], 6 is 3rd element of [4, 5, 6].
and so on.
(Edited) Note: I would like the result to be in the same order as the original element of the list. [1, 8, 6] but not [1, 6, 8] because 8 is the 2nd element of [7, 8, 9].
What you're looking for is the Cartesian product, in Python itertools.product:
>>> import itertools
>>> list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> all_possibility = list(itertools.product(*list_of_lists))
>>> print(all_possibility)
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 6, 7), (1, 6, 8),
(1, 6, 9), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 6, 7),
(2, 6, 8), (2, 6, 9), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 5, 7), (3, 5, 8), (3, 5, 9),
(3, 6, 7), (3, 6, 8), (3, 6, 9)]
If you want permutations based on the indices rather than the values, you can use itertools.combinations to get the possible indices, then use those indices to get the respective values from the sub-lists, like this:
>>> list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> length = 3
>>> all_indices = list(itertools.permutations(range(length), length))
>>> all_possibility = [[l[i] for l,i in zip(list_of_lists, indices)] for indices in all_indices]
>>> print(all_possibility)
[[1, 5, 9], [1, 6, 8], [2, 4, 9], [2, 6, 7], [3, 4, 8], [3, 5, 7]]
I have to consider the indices as well. For example, (1, 4, 7) is excluded because 1, and 4 both are the 1st element from the list of the lists (from [1, 2, 3] and [4, 5, 6]). And actually (1, 4, 7) all of them are from the first component of the nested list. I need the cases with all the different indices.
So you actually just want to get the possible permutations of a “list selector” for each index in the output, i.e. these are what you are trying to get:
>>> list(itertools.permutations(range(3), 3))
[(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
And once you have that, you just need to translate into your list_of_lists where you access each index from the specified sublist:
>>> [[list_of_lists[k][i] for i, k in enumerate(comb)] for comb in itertools.permutations(range(3), 3)]
[[1, 5, 9], [1, 8, 6], [4, 2, 9], [4, 8, 3], [7, 2, 6], [7, 5, 3]]
In a spirit of #poke's approach, here is the cases for number of elements differ than the number of the list in the lists. (Previously, there are 3 elements in individual list where 3 sub-lists in the list).
list_of_lists = [[1, 2], [3, 4], [5, 6], [7, 8]]
We expect every (0, 1) pairs from the list of lists, or
all_possibility = [[1, 4], [1, 6], [1, 8], [3, 2], [3, 6], [3, 8], \
[5, 2], [5, 4], [5, 8], [7, 2], [7, 4], [7, 6]]
The code:
permutation_cases = list(itertools.permutations(range(2), 2))
select_from = list(itertools.combinations(range(len(list_of_lists)), 2))
all_possibility = []
for selecting_index in select_from:
selected = [list_of_lists[i] for i in selecting_index ]
cases = list([selected[k][i] for i, k in enumerate(comb)] for comb in permutation_cases)
for item in cases:
all_possibility.append(item)
print(all_possibility)

What is the most elegant way of finding the n-length consecutive sub-lists of a list in Python?

Let's say I have some_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9] and I want to find all 3 element consecutive sub-lists: [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9].
What's the most elegant way of doing this?
>>> some_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l = [some_lst[i:i+3] for i in xrange(len(some_lst)-2)]
Another option is slices and zip:
>>> some_lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> zip(some_lst, some_lst[1:], some_lst[2:])
[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7), (6, 7, 8), (7, 8, 9)]
With itertools.islice and itertools.izip you can make it more memory-efficient:
from itertools import islice, izip
izip(islice(some_lst, 0, None),
islice(some_lst, 1, None),
islice(some_lst, 2, None))
or
izip(*[islice(some_lst, s, None) for s in range(3)])
yet another way:
subLists = map(lambda x: some_lst[x-1:x+2], some_lst[:-2])

Python - List Comprehension of List of Lists [duplicate]

This question already has answers here:
how to get all possible combination of items from 2-dimensional list in python?
(3 answers)
Closed 9 years ago.
I have a list of lists, and would like to generate a list of lists consisting of one element from each list.
For example, given the lists [[1, 2], [3, 4], [5, 6], [7, 8], I would execute the following code [(i, j, k, h) for i in [1, 2] for j in [3, 4] for k in [5, 6] for h in [7, 8]] and gets as output
[(1, 3, 5, 7), (1, 3, 5, 8), (1, 3, 6, 7), (1, 3, 6, 8), (1, 4, 5, 7), (1, 4, 5, 8), (1, 4, 6, 7), (1, 4, 6, 8), (2, 3, 5, 7), (2, 3, 5, 8), (2, 3, 6, 7), (2, 3, 6, 8), (2, 4, 5, 7), (2, 4, 5, 8), (2, 4, 6, 7), (2, 4, 6, 8)]
This code does not adapt for list of lists with different number of sub-lists. Is there a way to use nested list comprehensions to achieve the desired result? (My sub-lists are not always of the same length).
Use itertools.product, and unpack the list when pass as argument:
In [40]: from itertools import product
In [41]: list(product(*[[1, 2], [3, 4], [5, 6], [7, 8]]))
Out[41]:
[(1, 3, 5, 7),
(1, 3, 5, 8),
(1, 3, 6, 7),
(1, 3, 6, 8),
(1, 4, 5, 7),
(1, 4, 5, 8),
(1, 4, 6, 7),
(1, 4, 6, 8),
(2, 3, 5, 7),
(2, 3, 5, 8),
(2, 3, 6, 7),
(2, 3, 6, 8),
(2, 4, 5, 7),
(2, 4, 5, 8),
(2, 4, 6, 7),
(2, 4, 6, 8)]

Zip as a list comprehension

I have a fairly last list of data like this:
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I'm trying to zip it so that that I get something like this:
zipped_data = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
I know I could do that with
l = [(data[0]), (data[1]), (data[2])]
zipped_data = zip(*l)
But I would like to write a list comprehension to do that for any number of items in data. I tried this, but it didn't work.
s = [zip(i) for i in data]
s
[[(1,), (2,), (3,)], [(4,), (5,), (6,)], [(7,), (8,), (9,)]]
Can anyone identify where I've gone wrong here? Thanks.
Try the *:
In [2]: lis=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [3]: zip(*lis)
Out[3]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
If you really want to rewrite zip as a list comprehension, then this is how I would do it:
In [25]: data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [26]: [tuple(lis[j] for lis in data) for j in range(min(len(l) for l in data))]
Out[26]: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
In [27]: data = [[1, 2, 3], [4, 5, 6], [7, 8]]
In [28]: [tuple(lis[j] for lis in data) for j in range(min(len(l) for l in data))]
Out[28]: [(1, 4, 7), (2, 5, 8)]
Though, zip(*data) is definitely a better way to go about this
I would do it with zip but here is done with list comprehension
def zip_lists(lists):
"""
Assuming all lists have the same length
>>> zip_lists([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
>>> zip_lists([[1, 2], [3, 4], [5, 6], [7, 8]])
[[1, 3, 5, 7], [2, 4, 6, 8]]
"""
return [[l[x] for l in lists] for x in range(len(lists[0]))]

All combinations of a list of lists [duplicate]

This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 8 months ago.
I'm basically looking for a python version of Combination of List<List<int>>
Given a list of lists, I need a new list that gives all the possible combinations of items between the lists.
[[1,2,3],[4,5,6],[7,8,9,10]] -> [[1,4,7],[1,4,8],...,[3,6,10]]
The number of lists is unknown, so I need something that works for all cases. Bonus points for elegance!
you need itertools.product:
>>> import itertools
>>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
>>> list(itertools.product(*a))
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]
The most elegant solution is to use itertools.product in python 2.6.
If you aren't using Python 2.6, the docs for itertools.product actually show an equivalent function to do the product the "manual" way:
def product(*args, **kwds):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
Simply use itertools.product:
listOLists = [[1,2,3],[4,5,6],[7,8,9,10]]
for l in itertools.product(*listOLists):
print(l)
Nothing wrong with straight up recursion for this task, no need for external dependencies, and if you need a version that works with strings, this might fit your needs:
combinations = []
def combine(terms, accum):
last = (len(terms) == 1)
n = len(terms[0])
for i in range(n):
item = accum + terms[0][i]
if last:
combinations.append(item)
else:
combine(terms[1:], item)
>>> a = [['ab','cd','ef'],['12','34','56']]
>>> combine(a, '')
>>> print(combinations)
['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']
Numpy can do it:
>>> import numpy
>>> a = [[1,2,3],[4,5,6],[7,8,9,10]]
>>> [list(x) for x in numpy.array(numpy.meshgrid(*a)).T.reshape(-1,len(a))]
[[ 1, 4, 7], [1, 5, 7], [1, 6, 7], ....]
One can use base python for this. The code needs a function to flatten lists of lists:
def flatten(B): # function needed for code below;
A = []
for i in B:
if type(i) == list: A.extend(i)
else: A.append(i)
return A
Then one can run:
L = [[1,2,3],[4,5,6],[7,8,9,10]]
outlist =[]; templist =[[]]
for sublist in L:
outlist = templist; templist = [[]]
for sitem in sublist:
for oitem in outlist:
newitem = [oitem]
if newitem == [[]]: newitem = [sitem]
else: newitem = [newitem[0], sitem]
templist.append(flatten(newitem))
outlist = list(filter(lambda x: len(x)==len(L), templist)) # remove some partial lists that also creep in;
print(outlist)
Output:
[[1, 4, 7], [2, 4, 7], [3, 4, 7],
[1, 5, 7], [2, 5, 7], [3, 5, 7],
[1, 6, 7], [2, 6, 7], [3, 6, 7],
[1, 4, 8], [2, 4, 8], [3, 4, 8],
[1, 5, 8], [2, 5, 8], [3, 5, 8],
[1, 6, 8], [2, 6, 8], [3, 6, 8],
[1, 4, 9], [2, 4, 9], [3, 4, 9],
[1, 5, 9], [2, 5, 9], [3, 5, 9],
[1, 6, 9], [2, 6, 9], [3, 6, 9],
[1, 4, 10], [2, 4, 10], [3, 4, 10],
[1, 5, 10], [2, 5, 10], [3, 5, 10],
[1, 6, 10], [2, 6, 10], [3, 6, 10]]
This mostly mimics solutions like Answer by Jarret Hardie using itertools.product, but has these distinctions:
this passes parameters to itertools.product in-line, instead of via variable a - so no *args syntax needed on the inline parameters
if your mypy type-linter acts like mine, and you can get your code to otherwise "work" with the *args syntax with inline product parameters (like product(*[[1,2,3],[4,5,6],[7,8,9,10]])), mypy might still fail it (with something like error: No overload variant of "product" matches argument type "List[object]")
So solution to that mypy, is to not use *args syntax, like this:
>>> import itertools
>>> list(itertools.product([1,2,3],[4,5,6],[7,8,9,10]))
[(1, 4, 7), (1, 4, 8), (1, 4, 9), (1, 4, 10), (1, 5, 7), (1, 5, 8), (1, 5, 9), (1, 5, 10), (1, 6, 7), (1, 6, 8), (1, 6, 9), (1, 6, 10), (2, 4, 7), (2, 4, 8), (2, 4, 9), (2, 4, 10), (2, 5, 7), (2, 5, 8), (2, 5, 9), (2, 5, 10), (2, 6, 7), (2, 6, 8), (2, 6, 9), (2, 6, 10), (3, 4, 7), (3, 4, 8), (3, 4, 9), (3, 4, 10), (3, 5, 7), (3, 5, 8), (3, 5, 9), (3, 5, 10), (3, 6, 7), (3, 6, 8), (3, 6, 9), (3, 6, 10)]
This answer isn't as clean as using itertools but the ideas could be useful.
Drawing inspiration from the construction of zip() here, we could do the following.
>>> a = iter([[1,2,3],[4,5,6],[7,8,9,10]])
>>> sentinel = object()
>>> result = [[]]
>>> while True:
>>> l = next(a,sentinel)
>>> if l == sentinel:
>>> break
>>> result = [ r + [digit] for r in result for digit in l]
>>> print(result)
[[1, 4, 7], [1, 4, 8], [1, 4, 9], [1, 4, 10], [1, 5, 7], [1, 5, 8], [1, 5, 9], [1, 5, 10], [1, 6, 7], [1, 6, 8], [1, 6, 9], [1, 6, 10], [2, 4, 7], [2, 4, 8], [2, 4, 9], [2, 4, 10], [2, 5, 7], [2, 5, 8], [2, 5, 9], [2, 5, 10], [2, 6, 7], [2, 6, 8], [2, 6, 9], [2, 6, 10], [3, 4, 7], [3, 4, 8], [3, 4, 9], [3, 4, 10], [3, 5, 7], [3, 5, 8], [3, 5, 9], [3, 5, 10], [3, 6, 7], [3, 6, 8], [3, 6, 9], [3, 6, 10]]
We use a as an iterator in order to successively get the next item of it without needing to know how many there are a priori. The next command will output sentinel (which is an object created solely to make this comparison, see here for some explanation) when we run out of lists in a, causing the if statement to trigger so we break out of the loop.
from itertools import product
list_vals = [['Brand Acronym:CBIQ', 'Brand Acronym :KMEFIC'],['Brand Country:DXB','Brand Country:BH']]
list(product(*list_vals))
Output:
[('Brand Acronym:CBIQ', 'Brand Country :DXB'),
('Brand Acronym:CBIQ', 'Brand Country:BH'),
('Brand Acronym :KMEFIC', 'Brand Country :DXB'),
('Brand Acronym :KMEFIC', 'Brand Country:BH')]

Categories

Resources