Create all combinations of two sets of lists in Python - python

I am trying to create all combinations of two sets of lists using as follows:
x = [[1,2,3],[4,5,6]]
y = [['a','b','c'],['d','e','f']]
combos = [[1,2,3,'a','b','c'],[4,5,6,'d','e','f'],[4,5,6,'a','b','c'],[4,5,6,'d','e','f']]
I think itertools may be of some help but not sure how. Thanks

You can use product and chain:
from itertools import product, chain
[list(chain(*i)) for i in product(x, y)]
#[[1, 2, 3, 'a', 'b', 'c'],
# [1, 2, 3, 'd', 'e', 'f'],
# [4, 5, 6, 'a', 'b', 'c'],
# [4, 5, 6, 'd', 'e', 'f']]
Or you can use a list comprehension:
[i + j for i in x for j in y]
#[[1, 2, 3, 'a', 'b', 'c'],
# [1, 2, 3, 'd', 'e', 'f'],
# [4, 5, 6, 'a', 'b', 'c'],
# [4, 5, 6, 'd', 'e', 'f']]

Related

Merging 2 arrays in Python

I have 2 arrays:
first_arr = ['A', 'B', 'C', 'D', 'E', 'F']
second_arr = [1, 2, 3, 4, 5, 6]
And I'd like to unite them to an array or a list like this:
third_arr = [['A',1], ['B',2], ['C',3], ['D',4], ['E',5], ['F',6]]
or my_list = [['A',1], ['B',2], ['C',3], ['D',4], ['E',5], ['F',6]]
What is the easiest way to do it?
You can use zip() to merge the arrays...
first_arr = ['A', 'B', 'C', 'D', 'E', 'F']
second_arr = [1, 2, 3, 4, 5, 6]
third_arr = list(zip(first_arr, second_arr))
print(third_arr)
Which results in...
[('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5), ('F', 6)]
There is no difference between ('A',1) and ['A',1] in most cases. However, if you want to, you can change then from tuples to lists by assigning third_arr to the following...
...
third_arr = [list(t) for t in zip(first_arr, second_arr)]
print(third_arr)
Which results in...
[['A', 1], ['B', 2], ['C', 3], ['D', 4], ['E', 5], ['F', 6]]
Starting with the two lists, you can create a third list joining the elements of the two lists using the method .append() in a for loop:
first_arr = ['A', 'B', 'C', 'D', 'E', 'F']
second_arr = [1, 2, 3, 4, 5, 6]
my_list = []
for i in range(0,len(first_arr)):
my_list.append([first_arr[i],second_arr[i]])
my_list
[['A', 1], ['B', 2], ['C', 3], ['D', 4], ['E', 5], ['F', 6]]

Combing 2 lists, n elements each at a time

Given two equal length lists:
a = [1,2,3,4,5,6,7,8,9]
b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
Is there anyway to combine them, the first 3 (or more generally and for larger lists, the first n) elements of each at a time, such that I get an list output below:
c = [1,2,3,a,b,c,4,5,6,d,e,f,7,8,9,f,h,i]
I've seen solutions which show how to do it for 1 element at a time from each list but I can't translate that to n elements.
>>> list(itertools.chain.from_iterable(
a[p:p+n] + b[p:p+n] for p in range(0, len(a), n)))
[1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']
Using list slicing
Ex:
a = [1,2,3,4,5,6,7,8,9]
b = ['a','b','c','d','e','f','g','h','i']
res = []
for i in range(0, len(a), 3):
res.extend(a[i:i+3] + b[i:i+3])
print(res)
Output:
[1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']
Try list comprehension:
lst = [a[i:i+3] + b[i:i+3] for i in range(0, len(a), 3)]
result = [i for s in lst for i in s]
print (result)
Answer
[1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']
Here is a functional efficient (fast) way without any mutation using the itertools grouper recipe. Another advantage is that it can be used with any number of lists, not just two.
from itertools import zip_longest, chain
a = [1,2,3,4,5,6,7,8,9]
b = 'a,b,c,d,e,f,g,h,i'.split(',')
def grouper(iterable, n, fillvalue = None):
"""Collect data into fixed-length chunks or blocks
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
"""
args = [iter(iterable)]*n
return zip_longest(*args, fillvalue=fillvalue)
def multi_round_robin(*iterables, n, fillvalue = None):
""" Collect data from multiple iterables in groups
# multi_round_robin('ABCD', 'EFGH', n=2) --> A B E F C D G H
"""
for tups in zip(*(grouper(itr, n, fillvalue) for itr in iterables)):
return chain.from_iterable(tups)
list(multi_round_robin(a, b, n=3))
# --> [1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']
You can do this with simple for-loop and slices, where n - arrays length:
result = []
for j in range(0, len(a), n):
result += a[j:j+n] + b[j:j+n]
print(result)
I would use a function such as the following
def create_list(arr1, arr2, n):
c = []
for i in range(len(arr1)//n):
for j in range(3):
c.append(arr1[(i*3)+j])
for j in range(3):
c.append(arr2[(i*3)+j])
return c
This should give you the kind of list you were looking for.
Here's one way to do it:
In [14]: a
Out[14]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [15]: b
Out[15]: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
In [17]: al = [a[i:i+3] for i in range(0, len(a), 3)]
In [18]: bl = [b[i:i+3] for i in range(0, len(b), 3)]
In [19]: al
Out[19]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [20]: bl
Out[20]: [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']]
In [23]: [k for i in list(zip(al, bl)) for j in i for k in j]
Out[23]: [1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']
You can easily make a small function to perform this:
a = [1,2,3,4,5,6,7,8,9]
b = ['a','b','c','d','e','f','g','h','i']
def interleave( listA, listB, interval):
result = []
while len(listB) >= interval and len(listA) >= interval:
[result.append( listA.pop(0) ) for i in range(interval)]
[result.append( listB.pop(0) ) for i in range(interval)]
#Add remainder of lists in order
[result.append( item ) for item in listA]
[result.append( item ) for item in listB]
return result
print( interleave(a, b, 3) )
results in
[1, 2, 3, 'a', 'b', 'c', 4, 5, 6, 'd', 'e', 'f', 7, 8, 9, 'g', 'h', 'i']

python: combine lists of lists for SQLITE table

I need to combine 3 lists into one list so that I can insert it smoothly into sqlite table.
list1= [[a1,b1,c1],[a2,b2,c2]]
list2= [[d1,e1,f1],[d2,e2,f2]]
Output should look like:
combined_list = [[a1,b1,c1,d1,e1,f1],[a2,b2,c2,d2,e2,f2]]
I tried sum list1 + list2 but both didn't work as this output.
You can try this:
from operator import add
a=[[1, 2, 3], [4, 5, 6]]
b=[['a', 'b', 'c'], ['d', 'e', 'f']]
print a + b
print map(add, a, b)
Output:
[[1, 2, 3], [4, 5, 6], ['a', 'b', 'c'], ['d', 'e', 'f']]
[[1, 2, 3, 'a', 'b', 'c'], [4, 5, 6, 'd', 'e', 'f']]
Edit:
To add more than two arrays:
u=[[]]*lists[0].__len__()
for x in lists:
u=map(add, u, x)

Python_grouping multidimensional list

I have an example multidimensional list:
example_list=[
["a","b","c", 2,4,5,7],
["e","f","g",0,0,1,5],
["e","f","g", 1,4,5,7],
["a","b","c", 3,2,5,7]
]
How is it possible to put them in groups like this:
out_list=[
[["a","b","c", 2,4,5,7],
["a","b","c",3,2,5,7]
],
[["e","f","g", 0,0,1,5],
["e","f","g", 1,4,5,7]
]
]
I have tried this:
example_list=[["a","b","c", 2,4,5,7],["e","f","g", 0,0,1,5],["e","f","g",1,4,5,7],["a","b","c", 3,2,5,7]]
unique=[]
index=0
for i in range(len(example_list)):
newlist=[]
if example_list[i][:3]==example_list[index][:3]:
newlist.append(example_list[i])
index=index+1
unique.append(newlist)
print unique
My results is this:
[[['a', 'b', 'c', 2, 4, 5, 7]], [['e', 'f', 'g',0, 0, 1, 5]], [['e', 'f', 'g', 1, 4, 5, 7]], [['a', 'b', 'c', 3, 2, 5,7]]]
I could not figure it out.
If the grouping is decided by the first three elements in each list following code will do what you're asking for:
from collections import defaultdict
example_list=[["a","b","c", 2,4,5,7],["e","f","g",0,0,1,5],["e","f","g", 1,4,5,7],["a","b","c", 3,2,5,7]]
d = defaultdict(list)
for l in example_list:
d[tuple(l[:3])].append(l)
print d.values() # [[['a', 'b', 'c', 2, 4, 5, 7], ['a', 'b', 'c', 3, 2, 5, 7]], ...]
This will use defaultdict to generate a dictionary where keys are the first three elements and values are list of lists which start with those elements.
First sort the list simply using sorted(), providing a lambda function as key.
>>> a = sorted(example_list, key=lambda x:x[:3])
[['a', 'b', 'c', 2, 4, 5, 7], ['a', 'b', 'c', 3, 2, 5, 7], ['e', 'f', 'g', 0, 0, 1, 5], ['e', 'f', 'g', 1, 4, 5, 7]]
And then use itertools.groupby() on the sorted list:
>>> [list(v) for k, v in groupby(a, lambda x:x[:3])]
[
[['a', 'b', 'c', 2, 4, 5, 7], ['a', 'b', 'c', 3, 2, 5, 7]],
[['e', 'f', 'g', 0, 0, 1, 5], ['e', 'f', 'g', 1, 4, 5, 7]]
]

extracting a range of elements from a csv / 2d array

I want to extract elements from a range of elements is a specific column from a csv file.
I've simplified the problem to this:
data = [['a',1,'A',100],['b',2,'B',200],['c',3,'C',300],['d',4,'D',400]]
print(data[0:2][:],'\nROWS 0&1')
print(data[:][0:2],'\nCOLS 1&1')
I thought that meant
'show me all columns for just row 0 and 1'
'show me all the rows for just column 0 and 1'
But the output is always just showing me rows 0 and 1, never the columns,
[['a', 1, 'A', 100], ['b', 2, 'B', 200]]
ROWS 0&1
[['a', 1, 'A', 100], ['b', 2, 'B', 200]]
COLS 1&1
when I want to see this:
['a', 1, 'A', 100,'b', 2, 'B', 200] # ... i.e. ROWS 0 and 1
['a','b','c','d',1,2,3,4]
Is there a nice way to do this?
Your problem here is that data[:] is just a copy of data:
>>> data
[['a', 1, 'A', 100], ['b', 2, 'B', 200], ['c', 3, 'C', 300], ['d', 4, 'D', 400]]
>>> data[:]
[['a', 1, 'A', 100], ['b', 2, 'B', 200], ['c', 3, 'C', 300], ['d', 4, 'D', 400]]
... so both your attempts at slicing are giving you the same result as data[0:2].
You can get just columns 0 and 1 with a list comprehension:
>>> [x[0:2] for x in data]
[['a', 1], ['b', 2], ['c', 3], ['d', 4]]
... which can be rearranged to the order you want with zip():
>>> list(zip(*(x[0:2] for x in data)))
[('a', 'b', 'c', 'd'), (1, 2, 3, 4)]
To get a single list rather than a list of 2 tuples, use itertools.chain.from_iterable():
>>> from itertools import chain
>>> list(chain.from_iterable(zip(*(x[0:2] for x in data))))
['a', 'b', 'c', 'd', 1, 2, 3, 4]
... which can also be used to collapse data[0:2]:
>>> list(chain.from_iterable(data[0:2]))
['a', 1, 'A', 100, 'b', 2, 'B', 200]

Categories