Append cumulative list of lists python - 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]]

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]]

Merging multiple lists into one in 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)

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())

How can I generate a permutation of a list of lists while maintaining order on the highest level in Python?

I am looking for a simple way to solve this.
Lets say I have a list of lists, of which there are an uncertain number of lists in those lists:
lists = [
[[1,2,3,4],[2,3,4,5]],
[[1,2,3,4],[2,3,4,5],[3,4,5,6]],
[[1,2,3,4]],
[[1,2,3,4],[2,3,4,5]]
]
What I can't figure out is now to generate a permutation of all possible combinations while keeping the first level of lists in the same order. I have messed around with nested for loops and the any() function with little success. The nested for loops do not work, because in reality, len(lists) is much larger, and would take len(lists) amount of for loops. Does anyone have any ideas?
In the above example, a few possible permutations would be:
[[1,2,3,4],
[1,2,3,4],
[1,2,3,4],
[1,2,3,4]]
[[1,2,3,4],
[1,2,3,4],
[1,2,3,4],
[2,3,4,5]]
[[2,3,4,5],
[1,2,3,4],
[1,2,3,4],
[2,3,4,5]]
[[2,3,4,5],
[3,4,5,6],
[1,2,3,4],
[2,3,4,5]]
As #DSM suggests, you may be looking for the cartesian product. Permutations means something different.
>>> import pprint, itertools as it
>>> lists = [
... [[1,2,3,4],[2,3,4,5]],
... [[1,2,3,4],[2,3,4,5],[3,4,5,6]],
... [[1,2,3,4]],
... [[1,2,3,4],[2,3,4,5]]
... ]
>>> pprint.pprint(list(it.product(*lists)))
[([1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]),
([1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4, 5]),
([1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]),
([1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5]),
([1, 2, 3, 4], [3, 4, 5, 6], [1, 2, 3, 4], [1, 2, 3, 4]),
([1, 2, 3, 4], [3, 4, 5, 6], [1, 2, 3, 4], [2, 3, 4, 5]),
([2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]),
([2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [2, 3, 4, 5]),
([2, 3, 4, 5], [2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]),
([2, 3, 4, 5], [2, 3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5]),
([2, 3, 4, 5], [3, 4, 5, 6], [1, 2, 3, 4], [1, 2, 3, 4]),
([2, 3, 4, 5], [3, 4, 5, 6], [1, 2, 3, 4], [2, 3, 4, 5])]

How to make a set of lists

I have a list of lists like this:
i = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
I would like to get a list containing "unique" lists (based on their elements) like:
o = [[1, 2, 3], [2, 4, 5]]
I cannot use set() as there are non-hashable elements in the list. Instead, I am doing this:
o = []
for e in i:
if e not in o:
o.append(e)
Is there an easier way to do this?
You can create a set of tuples, a set of lists will not be possible because of non hashable elements as you mentioned.
>>> l = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
>>> set(tuple(i) for i in l)
{(1, 2, 3), (2, 4, 5)}
i = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
print([ele for ind, ele in enumerate(i) if ele not in i[:ind]])
[[1, 2, 3], [2, 4, 5]]
If you consider [2, 4, 5] to be equal to [2, 5, 4] then you will need to do further checks
You can convert each element to a tuple and then insert it in a set.
Here's some code with your example:
tmp = set()
a = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
for i in a:
tmp.add(tuple(i))
tmp will be like this:
{(1, 2, 3), (2, 4, 5)}
Here's another way to do it:
I = [[1, 2, 3], [2, 4, 5], [1, 2, 3], [2, 4, 5]]
mySet = set()
for j in range(len(I)):
mySet = mySet | set([tuple(I[j])])
print(mySet)

Categories

Resources