Merging multiple lists into one in Python - python

I have a list X. I want to append elements of X[0][0],X[1][0],X[2][0], X[1][0],X[1][1],X[2][1] and so on. I present the current and expected outputs.
X=[[[1], [2], [3], [4], [5]], [[8], [4], [6], [2], [3]],[[9], [1], [2], [5], [1]]]
X1=[]
for i in range(0,len(X)):
for j in range(0,len(X[0])):
X1=X[i][j]
X1.append(X)
The current output is
[1,
[[[1, [...]], [2, [...]], [3, [...]], [4, [...]], [5, [...]]],
[[8, [...]], [4, [...]], [6, [...]], [2, [...]], [3, [...]]],
[[9, [...]], [1, [...]], [2, [...]], [5, [...]], [...]]]]
The expected output is
[[1,8,9], [2,4,1], [3,6,2], [4,2,5], [5,3,1]]

Iterate over the sublists using zip, then add each inner lists, you can use list-comprehension for it:
>>> [x+y+z for (x,y,z) in zip(X[0], X[1], X[2])]
[[1, 8, 9], [2, 4, 1], [3, 6, 2], [4, 2, 5], [5, 3, 1]]
Or you can use reduce from functools and pass unpacked list to zip if you are not sure how many sublists are there
>>> from functools import reduce
>>> [reduce(lambda x,y: x+y, v) for v in zip(*X)]
[[1, 8, 9], [2, 4, 1], [3, 6, 2], [4, 2, 5], [5, 3, 1]]
Another approach is to call sum iterating the unpacked list passed to zip as suggested by #Mad Physicist in the comment:
>>> [sum(x, start=[]) for x in zip(*X)]
[[1, 8, 9], [2, 4, 1], [3, 6, 2], [4, 2, 5], [5, 3, 1]]

You can use numpy instead of dealing with loops
import numpy as np
array = np.array([[[1], [2], [3], [4], [5]], [[8], [4], [6], [2], [3]],[[9], [1], [2], [5], [1]]])
// reshape and transpose
array = array.reshape(3,5).T
array will be
array([[1, 8, 9],
[2, 4, 1],
[3, 6, 2],
[4, 2, 5],
[5, 3, 1]])

Numpy can help a lot here. First when get rid of the inner-most single-item lists, turning the three list[list[int]] into three list[int]. Then, those can be used to create a np.ndarray. We then transpose this array to get the desired result.
import numpy as np
X = [[[1], [2], [3], [4], [5]],
[[8], [4], [6], [2], [3]],
[[9], [1], [2], [5], [1]]]
a = [[item[0] for item in sublist] for sublist in X]
# [[1, 2, 3, 4, 5], [8, 4, 6, 2, 3], [9, 1, 2, 5, 1]]
a = np.array(a).T
# array([[1, 8, 9],
# [2, 4, 1],
# [3, 6, 2],
# [4, 2, 5],
# [5, 3, 1]])

If there are fewer and more than 3 elements:
import numpy as np
x=[[[1], [2], [3], [4], [5]], [[8], [4], [6], [2], [3]],[[9], [1], [2], [5], [1]]]
x = np.asarray(x)
x = x.reshape(x.shape[0],x.shape[1]).T
x
Output for(3,5,1):
array([[1, 8, 9],
[2, 4, 1],
[3, 6, 2],
[4, 2, 5],
[5, 3, 1]])
Output for (4,5,1):
array([[1, 8, 9, 9],
[2, 4, 1, 1],
[3, 6, 2, 2],
[4, 2, 5, 5],
[5, 3, 1, 1]])

As your list (X) contains a few lists with the same size, it's number of elements can be just indexes_per_list = len(X[0]).
We can then search for the index in every sub-list, and append the correct index.
In order to remove the square brackets, we just use explode (*):
output = []
indexes_per_list = len(X[0])
for i in range(indexes_per_list):
item = []
for l in X:
item.append(*l[i])
output.append(item)
print(output)

Related

Addition to nested list

I wanted to add element with the next value to the most nested list, i. e.
For list
list_in = [2, 3, [4, 5, [6, 7], 6], 2, [5, 6]]
The program should return
list_out = [2, 3, [4, 5, [6, 7, 8], 6], 2, [5, 6]]
In case with e. x. two equal nests, I wanted to get:
list_in = [2, [4], [3]]
list_out = [2, [4, 5], [3, 4]]
How to do it?
A recursive solution:
list_in = [2, 3, [4, 5, [6, 7], 6], 2, [5, 6]]
def get_depths(lst, depths, current_depth=0):
out = [
get_depths(v, depths, current_depth + 1) if isinstance(v, list) else v
for v in lst
]
depths.setdefault(current_depth, []).append(out)
return out
depths = {}
list_out = get_depths(list_in, depths)
for lst in depths[max(depths)]:
lst.append(lst[-1] + 1)
print(list_out)
Prints:
[2, 3, [4, 5, [6, 7, 8], 6], 2, [5, 6]]
For list_in = [2, [4], [3]] it prints:
[2, [4, 5], [3, 4]]

Pythonic way to find all the different intersections and differences between two lists of arrays

This is the generalization of a previous question of mine. I need to find all the intersections and differences between two lists of different arrays. There are no intersections within the arrays of any of the lists, only between the arrays in different lists.
The expected result for the next example
x = [np.array([0, 6, 7, 10]), np.array([1, 2, 5, 9])]
y = [np.array([ 7, 10]), np.array([8]), np.array([0, 3, 4, 5])]
should be
[[0], [6], [7, 10], [1, 2, 9], [5], [8], [3, 4]]
Any suggestion? Thanks in advance!
There is no point to separate arguments, the result will be the same as you unite x and y. So you have set of sets and try to find separate pieces. To find them you can iterate through all elements and remember at which sets this value was encountered. Then if 2 elements have exactly the same set of sets (say they both met at second and forth sets) we return this elements as united group.
from collections import defaultdict
def pythonic(s):
"""
>>> pythonic([[0, 6, 7, 10], [1, 2, 5, 9], [7, 10], [0, 3, 4, 5]])
[[0], [6], [7, 10], [1, 2, 9], [5], [3, 4]]
>>> pythonic([[7, 10], [8], [0, 3, 4, 5], [0, 6, 7, 10], [1, 2, 5, 9]])
[[7, 10], [8], [0], [3, 4], [5], [6], [1, 2, 9]]
>>> pythonic([[0, 1, 4, 5], [1, 2, 3, 4], [3, 4, 5, 6]])
[[0], [1], [4], [5], [2], [3], [6]]
"""
all_elements = defaultdict(list)
for i, ss in enumerate(s):
for elem in ss:
all_elements[elem].append(i)
reversed = defaultdict(list)
for k, v in all_elements.items():
reversed[frozenset(v)].append(k) # or tuple can be used but "frozenset" feels "safer"
return list(reversed.values())

Append cumulative list of lists python

I am trying to extend a list of lists in a commulative way like this:
# Consider the following list of lists
l_Of_l = [ [1], [2], [3], [4], [5], [6], [7]]
Desired result is:
l_extended = [ [1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
So basically the size of the list remains the same after extending commulatively.
Edit:
Here is what I did initially:
l_Of_l = [ [1], [2], [3], [4], [5], [6], [7]]
lista = []
for i in l_Of_l:
lista.extend(i)
print(list([i for i in lista]))
But then the result was:
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
Does anyone know how to achieve this in the correct way?
Use accumulate from itertools:
list(itertools.accumulate(l_Of_l))
Out:
[[1],
[1, 2],
[1, 2, 3],
[1, 2, 3, 4],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6, 7]]
One way to do this without itertools is to use Python's sum function to concatenate lists.
>>> L = [ [1], [2], [3], [4], [5], [6], [7] ]
>>> L_extend = [ sum(L[0:i+1], []) for i in range(len(L)) ]
You want a cumulative sum, just with lists. itertools.accumulate can do this.
>>> from itertools import accumulate
>>> lst = [[1], [2], [3], [4], [5], [6], [7]]
>>> list(accumulate(lst))
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
You can also create a simple list comprehension:
>>> from operator import itemgetter
>>> l_Of_l = [[1], [2], [3], [4], [5], [6], [7]]
>>> [list(map(itemgetter(0), l_Of_l[:i+1])) for i in range(len(l_Of_l))]
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
Yet another method using list(range()) in list comprehension method.
lol = [ [1], [2], [3], [4], [5], [6], [7] ]
lol_test2 = [list(range(1, i+2))for i in range(len(lol))]
print(lol_test2)
Output:
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]
lol = [ [1], [2], [3], [4], [5], [6], [7] ]
lol_test = [[*range(1, i+2)]for i in range(len(lol))]
print(lol_test)
I came up with a solution similar to Bill M, just a small difference. I am just a novice learning python.
And it worked with the same output: [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7]]

Generator for splitting list (sequence) in N chunks in Python

for i in generate_chunks([1, 2, 3, 4, 5], 2):
print(i)
# [[1], [2, 3, 4, 5]]
# [[1, 2], [3, 4, 5]]
# [[1, 2, 3], [4, 5]]
# [[1, 2, 3, 4], [5]]
for i in generate_chunks([1, 2, 3, 4, 5], 3):
print(i)
# [[1], [2], [3, 4, 5]]
# [[1, 2], [3], [4, 5]]
# [[1, 2, 3], [4], [5]]
# [[1, 2], [3, 4], [5]]
# ...
How can I implement generate_chunks(list, n)?
Essentially what generate_chunks does is splitting list in n chunks and yield a list of these chunks.
For clarification, n refers to the number of chunks, not the length of the chunks.
The order in which those lists of chunks are yielded is irrelevant, however the order of the elements in the initial list is important, so that for a given list [1, 2, 3] the result [[1], [2, 3]] would be valid whereas [[1], [3, 2] would be invalid.
(Preferably without using a 3rd-party library)
Here is an itertools based approach:
import itertools
def chunks(items, cutpoints):
return [items[i:j] for i,j in zip([0] + cutpoints, cutpoints + [len(items)])]
def generate_chunks(items, n):
indices = range(1,len(items))
for cutpoints in itertools.combinations(indices,n-1):
yield chunks(items,list(cutpoints))
For example:
>>> for c in generate_chunks([1,2,3,4,5],4): print(c)
[[1], [2], [3], [4, 5]]
[[1], [2], [3, 4], [5]]
[[1], [2, 3], [4], [5]]
[[1, 2], [3], [4], [5]]

Permutations within and across list of lists [python]

There are many questions that are related but none that I could find to do exactly what I am looking for. Essentially, I want to get all permutations of each sub-list put together for all possible combinations but keeping them separate. As such:
input=[[1,2,3],[4],[5,6]]
desired output:
[[1,2,3],[4],[6,5]]
[[2,1,3],[4],[5,6]]
[[2,1,3],[4],[5,6]]
[[3,1,2],[4],[5,6]]
etc...
I believe the following code will work, but I was wondering if there were any more efficient or succinct strategies. Thank you very much.
input=[[1,2,3],[4],[5,6]]
all_lists=[]
for i in xrange(len(input)):
all_lists.append(list(itertools.permutations(input[i])))
all_combinations = list(itertools.product(*all_lists))
## concat them together
combinations_combined = [list(itertools.chain(*a)) for a in all_combinations]
We can first use list comprehension to generate all permutations for each sublist:
perms = [list(map(list,permutations(subl))) for subl in data]
and then we can use product to obtain products.
for data in product(*perms):
print(list(data))
Or in full:
from itertools import permutations, product
def product_perms(data):
perms = [list(map(list,permutations(subl))) for subl in data]
for data in product(*perms):
print(list(data))
This produces:
>>> product_perms(data)
[[1, 2, 3], [4], [5, 6]]
[[1, 2, 3], [4], [6, 5]]
[[1, 3, 2], [4], [5, 6]]
[[1, 3, 2], [4], [6, 5]]
[[2, 1, 3], [4], [5, 6]]
[[2, 1, 3], [4], [6, 5]]
[[2, 3, 1], [4], [5, 6]]
[[2, 3, 1], [4], [6, 5]]
[[3, 1, 2], [4], [5, 6]]
[[3, 1, 2], [4], [6, 5]]
[[3, 2, 1], [4], [5, 6]]
[[3, 2, 1], [4], [6, 5]]
In case you want to return such a list, you can use:
def product_perms(data):
perms = [list(map(list,permutations(subl))) for subl in data]
return [list(data) for data in product(*perms)]
And_the_case [[3, 1, 2], [4], [5, 6, [7,8[9,10,11]]? If it's nested list?

Categories

Resources