I have few lists that I want to concatenate into a new list of lists. For example, a list might look like this:
[[], []]
[[3], [1]]
[[], [5]]
[[2,5], []]
and based on this I want the output to look like:
[[3, 2, 5], [1,5]]
We cannot assume anything about the length of the lists (they will not always have two elements in the beginning, they might have more).
Here is the code I tried:
list1[l] += list2[l] #where l is an index
If we know that each top-level list shape matches all others, then we can do something like this using list comprehensions:
lists = [
[[], []],
[[3], [1]],
[[], [5]],
[[2,5], []],
]
shape=len(lists[0])
res = [[val for lst in lists for val in lst[i]] for i in range(shape) ]
print(res)
Output:
[[3, 2, 5], [1, 5]]
lst = [[[], []],[[3], [1]],[[], [5]],[[2,5], []]]
lstFinal = []
for i in range(0,len(lst[0])):
temp = []
for j in range(0,len(lst)):
temp.extend(lst[j][i])
lstFinal.append(temp)
print(lstFinal)
from functools import reduce
from operator import add
a = [[], []]
b = [[3], [1]]
c = [[], [5]]
d = [[2,5], []]
# transpose
z = zip(a, b, c, d)
# list(z) --> [([], [3], [], [2, 5]), ([], [1], [5], [])]
# flatten
def f(t):
return reduce(add, t)
m = map(f, z)
# result
for thing in m:
print(thing)
>>>
[3, 2, 5]
[1, 5]
>>>
Related
I have a nested list say:
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
And I would like the output to be:
new_list = [[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
this is what i am thinking, but I it is outputting a flat, list of list.
new_lst = []
for i in lst:
i = list(i)
for el in i:
new_list.append([el])
print(new_lst)
I would like to maintain the length of each predefined list in lst
Try List comprehension
[[ [e] for e in l] for l in lst]
You could use list comprehension and append every element to another list.
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
new = [[[numbers] for numbers in elements] for elements in lst]
The above example adjusts for your desired output.
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
You can use numpy's reshape np.reshape
>>> import numpy as np
>>> lst = np.array([[1,2,3,4], [2,3,4,5], [3,4,5,6]])
>>> lst
array([[1, 2, 3, 4],
[2, 3, 4, 5],
[3, 4, 5, 6]])
>>> lst.shape
(3, 4)
>>> lst.reshape(3,4,1)
array([[[1],
[2],
[3],
[4]],
[[2],
[3],
[4],
[5]],
[[3],
[4],
[5],
[6]]])
>>> lst.reshape(3,4,1).tolist()
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
Another version, using recursion (you can have more level of depths in your input):
lst = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
def split(i):
if isinstance(i, list):
return [split(v) for v in i]
else:
return [i]
print(split(lst))
Prints:
[[[1], [2], [3], [4]], [[2], [3], [4], [5]], [[3], [4], [5], [6]]]
You could use helper function to have more flexibility later of how you divide the smaller lists. based on an answer from here.
def split_list(alist, wanted_parts=1):
length = len(alist)
return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts]
for i in range(wanted_parts) ]
lst = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
ret =[]
for mini_list in lst:
ret.append(split_list(mini_list, len(mini_list)))
I think you had the right idea using multiple for loops. This should work:
list = [[1,2,3,4], [2,3,4,5], [3,4,5,6]]
for i in range(0, 3):
for j in range(0, 4):
(list[i])[j] = [(list[i])[j]]
I have a nested list like this,
l=[[],[],[1,2],[],[5],[],[4,3],[]]
Now I got the indices of the empty lists of the nested list.
indices=[0,1,3,5,7]
Now, I want to insert/append zero to the empty lists by index, so the list should look like,
l=[[0],[0],[1,2],[0],[5],[0],[4,3],[0]]
I can do it using,
x=[]
for i in l:
if len(i)==0:
x.append([0])
else:
x.append(i)
But the execution time will be huge, I am looking for sort cuts to do it efficiently.
You could use a list comprehension, but this wont guarantee an improvement in the execution time:
l = [[], [], [1, 2], [], [5], [], [4, 3], []]
result = [e or [0] for e in l]
print(result)
Output
[[0], [0], [1, 2], [0], [5], [0], [4, 3], [0]]
How to get all partitions of a set?
For example, I have array [1, 2, 3]. I need to get [[1], [2], [3]], [[1], [2, 3]], [[2], [1,3]], [[3], [1, 2]], [[1, 2, 3]].
Now, I wrote this code:
def neclusters(S, K):
for splits in itertools.combinations(range(len(S)), K):
yield np.split(S, 1 + np.array(splits))
But that code don't return [[2],[1,3]].
I could take all permutations of the original set and run this code on them. But can this be made easier?
I wrote this one for fun:
def partition(a_list):
yield [[x] for x in a_list]
for i in range(1, len(a_list) + 1):
_l = a_list[:]
yield [_l.pop(i-1), _l]
yield a_list
my_list = [1, 2, 3]
print list(partition(my_list))
#or
for p in partition(my_list):
print p
a = [1, 2, 3]
b = list()
for l in range(len(a)+1): b.append([c for c in combinations(a, l)])
print(b)
check this
Let's say I have a list:
l = [0,1,2,3,4]
And I want to obtain a sequence of lists in this logic:
[[1,2,3,4],[0,1,2,3],[2,3,4],[1,2,3],[0,1,2],[3,4],[2,3],[1,2],[0,1],[0],[1],[2],[3],[4]]
That's it, sublists made of l[1:] and l[:-1]
I started by this recursive function:
l = [0,1,2,3,4]
def sublist(l):
if len(l) == 1:
return l
else:
return [sublist(l[1:]),sublist(l[:-1])]
a = [sublist(l)]
print a
But it's not really what I what as it outputs:
[[[[[[4], [3]], [[3], [2]]], [[[3], [2]], [[2], [1]]]], [[[[3], [2]], [[2], [1]]], [[[2], [1]], [[1], [0]]]]]]
import itertools
[list(itertools.combinations(l, x)) for x in range(1, len(l))]
Here's a very straightforward implementation:
def sublists_n(l, n):
subs = []
for i in range(len(l)-n+1):
subs.extend([l[i:i+n]])
return subs
def sublists(l):
subs = []
for i in range(len(l)-1,0,-1):
subs.extend(sublists_n(l,i))
return subs
>>> l = [0,1,2,3,4]
>>> sublists(l)
[[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2], [1, 2, 3], [2, 3, 4], [0, 1], [1, 2], [2, 3], [3, 4], [0], [1], [2], [3], [4]]
[l[x:] for x in range(len(l))] + [l[:x+1] for x in range(len(l))]
Loops through l twice, but you sort of have to no matter what I think (could use zip but same thing).
A simple recursion, doesn't quite order things correctly but its simple.
def sublists(l):
right = l[1:]
left = l[:-1]
result = [right, left]
if len(l) > 2:
result.extend(sublists(right))
result.extend(sublists(left))
return result
print sublists([0,1,2,3,4])
This follows on from this question:
Algorithm to generate spanning set
Given this input: [1,2,3,4]
I'd like to generate this set of sets in python:
[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]
[1,2,3,4]
So unlike the previous question, the order of the list is retained.
Ideally the code would work for n items in the list
Thanks very much
EDIT 2: Could anyone advise me on how to do this if the original input is a string rather than a list (where each word in the string becomes an item in a list). Thanks!
EDIT: added [1] [2, 3, 4] Sorry for the mistake
You might also enjoy a recursive solution:
def span(lst):
yield [lst]
for i in range(1, len(lst)):
for x in span(lst[i:]):
yield [lst[:i]] + x
Explanation
We exploit recursion here to break the problem down. The approach is the following:
For every list, the whole list is a valid spanning: [1,2,3,4] => [[1,2,3,4]].
For every list that is longer than size 1, we can use the first item as a group and then apply the same algorithm on the remaining list to get all the combined results:
[1,2,3] =>
[[1]] + [[2], [3]] # => [[1], [2], [3]]
[[1]] + [[2,3]] # => [[1], [2,3]]
For every list that is longer than size 2, we can just as well use the first two items as a group and then apply the same algorithm on the remaining list and combine the results:
[1,2,3,4,5] =>
[[1,2]] + [[3], [4], [5]] # => [[1,2], [3], [4], [5]]
[[1,2]] + [[3,4], [5]] # => [[1,2], [3,4], [5]]
[[1,2]] + [[3], [4,5]] # => [[1,2], [3], [4,5]]
[[1,2]] + [[3,4,5]] # => [[1,2], [3,4,5]]
We can see that the possible combinations on the right side are indeed all possible groupings of the remainder of the list, [3,4,5].
For every list that is longer than ... etc. Thus, the final algorithm is the following:
yield the whole list (it is always a valid spanning, see above)
For every possible splitting of the list, yield the left-hand part of the list combined with all possible spannings of the right-hand part of the list.
yield is a special keyword in Python that make the function a generator, which means that it returns a iterable object that can be used to enumerate all results found. You can transform the result into a list using the list constructor function: list(span([1,2,3,4])).
Adjusting one of the solution from Python: show all possible groupings of a list:
from itertools import combinations
def cut(lst, indexes):
last = 0
for i in indexes:
yield lst[last:i]
last = i
yield lst[last:]
def generate(lst, n):
for indexes in combinations(list(range(1,len(lst))), n - 1):
yield list(cut(lst, indexes))
data = [1,2,3,4]
for i in range(1, len(data)+1): # the only difference is here
for g in generate(data, i):
print(g)
"""
[[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]]
[[1], [2], [3], [4]]
"""
import itertools
a = [1, 2, 3, 4]
n = len(a)
for num_splits in range(n):
for splits in itertools.combinations(range(1, n), num_splits):
splices = zip([0] + list(splits), list(splits) + [n])
print([a[i:j] for i, j in splices])
prints
[[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]]
[[1], [2], [3], [4]]