This question already has answers here:
How do I split a list into equally-sized chunks?
(66 answers)
Closed 9 years ago.
def group(l,size):
length = len(l)
new = []
for i in range(0,length):
for j in range(i,size):
new[i].append(l[j])
print new
The above function group(list, size) that take a list and splits into smaller lists of given size.
I need something like this
input: group([1, 2, 3, 4, 5, 6, 7, 8, 9], 3)
output: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
But the problem with the above code is showing index out of range.what's wrong in code?
how to append elements into list of lists?
Use slice.
>>> def group(l, size):
... return [l[i:i+size] for i in range(0, len(l), size)]
...
>>> group([1, 2, 3, 4, 5, 6, 7, 8, 9], 3)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
try:
def group(l,size):
length = len(l)
new = []
for i in range(0, length/size):
new.append([])
for i in range(0,len(new)):
for j in range(i*size,(i*size)+size):
new[i].append(l[i+j])
print new
edit:
no, don't do this. use slice like falsetru illustrates.
rough solution would be this :]
def group(l,size):
length = len(l)
newlist = []
newgroup = []
j = 0
for i in range(0,length):
if(j<size - 1):
j += 1
newgroup.append(l[i])
else:
j = 0
newgroup.append(l[i])
newlist.append(newgroup)
newgroup = []
if(newgroup != []):
newlist.append(newgroup)
return newlist
print(group([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3))
result: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]
Related
This question already has answers here:
Flatten an irregular (arbitrarily nested) list of lists
(51 answers)
Closed 1 year ago.
Trying to unnest this list: [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
Into this list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
So far this is my function:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnesting(L):
my_list = []
for element in (L):
if type(element) is list:
my_list.extend(element)
else:
my_list.append(element)
return my_list
except it gives me this output: [1, 2, 3, [4, 5, [6]], 7, 8, 9]
Any solutions or advice on how to unnest this list? Thank you!
You need recursion, otherwise, the function will only work for a nested depth of 2. The important realization is that when your list contains a list again, then you are facing the same problem, i.e. can call the same function again.
The following will work:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnest(lst1, lst2=None):
if lst2 is None:
lst2 = []
for x in lst1:
if not isinstance(x, list):
lst2.append(x)
else:
unnest(x, lst2)
return lst2
flattened = unnest(L)
print(flattened)
I think you're just looking for a short recursive solution here, try this:
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
def unnesting(my_list):
if type(my_list) == int:
return [my_list]
return sum((unnesting(elem) for elem in my_list), [])
print(unnesting(L))
Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]
If you have any questions about how this works, leave a comment below and I'll do my best to help you understand.
You can try this. I have just called the function recursively.
my_list = []
def unnesting(L):
for element in L:
if type(element) is list:
unnesting(element)
else:
my_list.append(element)
return my_list
well this is a little different way of doing this. I don't recommend doing it this way. But python allows us to get the result multiple ways.
def unnest(lst):
_ = str(lst)
_ = _.replace('[', '').replace(']', '').replace(',', '').replace(' ', '')
return [int(i) for i in _]
L = [1, [2, 3, [4, 5, [6]]], [7, 8], 9]
unnest(L)
The problem is regarding reversing a list A of size N in groups of K. For example if A = [1,2,3,4,5], k = 3
Output = [3,2,1,5,4]
The error I get, when I run this is List Index out of range on line 4.
def reverseInGroups(A,N,K):
arr1 = []
for i in range(K):
arr1.append(A[(N-i)%K]) #line 4
for j in range(N-K):
arr1.append(A[N-j-1])
return arr1
This will implement what you are trying to achieve:
def reverseInGroups(A,K):
N = len(A)
arr1 = []
for i in range(0, N, K):
arr1.extend(A[i : i+K][::-1])
return arr1
print(reverseInGroups([1,2,3,4,5], 3))
Interestingly, the code in the question actually works in the example case, but it is not general. The case where it works is where N = 2*K - 1 (although where it does not work, the elements are in the wrong order rather than an IndexError).
Cant seem to reproduce your 'List index out of range' error, but your logic is faulty:
reverseInGroups(A,N,K):
arr1 = []
for i in range(K):
arr1.append(A[(N-i)%K]) #line 4
for j in range(N-K):
arr1.append(A[N-j-1])
return arr1
print(reverseInGroups([1,2,3,4,5],5, 3)) # works, others get wrong result
print(reverseInGroups([1,2,3,4,5,6],6, 3)) # wrong result: [1, 3, 2, 6, 5, 4]
prints:
[3, 2, 1, 5, 4] # correct
[1, 3, 2, 6, 5, 4] # wrong
You fix this and make this smaller by packing it into a list comprehension:
def revv(L,k):
return [w for i in (L[s:s+k][::-1] for s in range(0,len(L),k)) for w in i]
for gr in range(2,8):
print(gr, revv([1,2,3,4,5,6,7,8,9,10,11],gr))
to get:
2 [2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 11]
3 [3, 2, 1, 6, 5, 4, 9, 8, 7, 11, 10]
4 [4, 3, 2, 1, 8, 7, 6, 5, 11, 10, 9]
5 [5, 4, 3, 2, 1, 10, 9, 8, 7, 6, 11]
6 [6, 5, 4, 3, 2, 1, 11, 10, 9, 8, 7]
7 [7, 6, 5, 4, 3, 2, 1, 11, 10, 9, 8]
You can also try with this:
def reverse(l, n):
result = []
for i in range(0, len(l)-1, n):
for item in reversed(l[i:i+n]):
result.append(item)
for item in reversed(l[i+n:]):
result.append(item)
return result
You can reverse the array upto index K and reverse the remaining part and add these both arrays.
def reverseInGroups(A,N,K):
return A[:K][::-1]+A[K:][::-1]
A = [1,2,3,4,5]
N = 5
K = 3
res = reverseInGroups(A,N,K)
print(res)
I want to split a list into sub-lists of a specified length. If the last chunk is not of the specified length, it will be augmented from the first element(s) of the list.
The below Python program produces equal sub-lists except for the last chunk.
def split_list(the_list, chunk_size):
result_list = []
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print split_list(a_list, 3)
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
I want something like this:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
Let's try a generator-based solution using itertools.cycle and islice:
from itertools import cycle, islice
def split_list(lst, n):
it = cycle(lst)
for i in range(len(lst) // n + len(lst) % n):
yield list(islice(it, n))
Call the function like this:
>>> a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(split_list(a_list, 3))
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
I personally prefer a generator here because the chunks are yielded one at a time, efficiently. If you want everything at once, you call list() on the result (like I've done).
Check to see whether you're going to be short in the last list chunk. If so, add exactly the needed quantity of elements, duplicated form the front of the list.
def split_list(the_list, chunk_size):
result_list = []
short = len(the_list) % chunk_size
if short:
# Add wrap-around elements from front of the_list
the_list.extend(the_list[:chunk_size-short])
while the_list:
result_list.append(the_list[:chunk_size])
the_list = the_list[chunk_size:]
return result_list
a_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(split_list(a_list, 3))
Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 1, 2]]
One way is to use a list comprehension and then add part of the start of the list to the final group if needed.
def split_list(the_list, chunk_size):
chunks = [the_list[i:i+chunk_size] for i in range(0, len(the_list), chunk_size)]
chunks[-1] += the_list[:(chunk_size - len(the_list)) % chunk_size]
return chunks
I have the following array [1, 4, 7, 9, 2, 10, 5, 8] and I need to separate the array in 3 different arrays: one for values between 0 and 3, anther for 3 to 6 and anther for 6 and 25.The result must be something like that:
array1 = [1, 2]
array2 = [4, 5]
array3 = [7, 9, 10, 8]
Any idea about how to do it simple?
First, define your "pole" numbers
Second, generate your intervals from those "pole" numbers
Third, define as many lists as there are intervals.
Then for each interval, scan the list and appends items in the relevant list if they belong to the interval
code:
source = [1, 4, 7, 9, 2, 10, 5, 8]
poles = (0,3,6,25)
intervals = [(poles[i],poles[i+1]) for i in range(len(poles)-1)]
# will generate: intervals = [(0,3),(3,6),(6,25)]
output = [list() for _ in range(len(intervals))]
for out,(start,stop) in zip(output,intervals):
for s in source:
if start <= s <stop:
out.append(s)
print(output)
result:
[[1, 2], [4, 5], [7, 9, 10, 8]]
This solution has the advantage of being adaptable to more than 3 lists/intervals by adding more "pole" numbers.
EDIT: There's a nice & fast solution (O(log(N)*N)) if the output lists order don't matter:
first sort the input list
then generate the sliced sub-lists using bisect which returns insertion position of the provided numbers (left & right)
like this:
import bisect
source = sorted([1, 4, 7, 9, 2, 10, 5, 8])
poles = (0,3,6,25)
output = [source[bisect.bisect_left(source,poles[i]):bisect.bisect_right(source,poles[i+1])] for i in range(len(poles)-1)]
print(output)
result:
[[1, 2], [4, 5], [7, 8, 9, 10]]
You can do that in a very simple way using a combination of a for loop and range functions:
lists = ([], [], [])
for element in [1, 4, 7, 9, 2, 10, 5, 8]:
if element in range(0, 3):
lists[0].append(element)
elif element in range(3, 6):
lists[1].append(element)
elif element in range(6, 25):
lists[2].append(element)
array1, array2, array3 = lists
"One-line" solution using set.intersection(*others) and range(start, stop[, step]) functions:
l = [1, 4, 7, 9, 2, 10, 5, 8]
l1, l2, l3 = (list(set(l).intersection(range(3))), list(set(l).intersection(range(3,6))), list(set(l).intersection(range(6,25))))
print(l1)
print(l2)
print(l3)
The output:
[1, 2]
[4, 5]
[8, 9, 10, 7]
https://docs.python.org/3/library/stdtypes.html?highlight=intersection#set.intersection
How can i split it into sequences/runs/subsequent-numbers, if the run is no longer than 3?
Having an array as follows
[1, 2, 3, 5, 9, 10, 16, 17, 18, 19]
My expected output would be the following arrays:
[1, 2, 3]
[5]
[9, 10]
[16, 17, 18]
[19]
e.g. [[1, 2, 3], [5], [9, 10], [16, 17, 18], [19]]
If it is a run of length 8 e.g. [1, 2, 3, 4, 5, 6, 7, 8] i would like to get 8 / 3 + 1 = 2 lists:
[1, 2, 3]
[4, 5, 6]
[7, 8]
If you name your current list, x and the new list of output, new_list, you can try (untested and assumes no repeat values in original list)
k = 0
new_list = [[]]
for i in range(len(x) - 1):
if x[i] not in new_list[max(k - 1, 0)]:
new_list[k].append(x[i])
for j in range(i + 1, len(x)):
if x[j] - x[i] == j - i and x[j] not in new_list[k]:
new_list[k].append(x[j])
k += 1
new_list.append([])
new_list = [x for x in new_list if x != []] # gets rid of empty list at the end
Here's my version that uses numpy:
import numpy as np
from itertools import chain
def split_list(mylist):
"""Function to do the initial split"""
# calculate differences
d = np.diff(mylist)
# when the differences are not 1 save that location
# we need a +1 to get make up for the lost element
breaks = list(np.arange(len(mylist) - 1)[d != 1] + 1)
slices = zip([0] + breaks, breaks + [len(mylist)])
# slice up the list
int_list = [mylist[a:b] for a, b in slices]
# chop up long sequences
chopped = [chop(l) for l in int_list]
# flatten the list once
return list(chain.from_iterable(chopped))
def chop(sublist, max_len=3):
"""Chops a list into chunks of length max_len"""
breaks = list(range(0, len(sublist), max_len))
slices = zip(breaks, breaks[1:] + [len(sublist)])
return [sublist[a:b] for a, b in slices]
Running this on the list's given:
>>> split_list([1, 2, 3, 5, 9, 10, 16, 17, 18, 19])
[[1, 2, 3], [5], [9, 10], [16, 17, 18], [19]]
Something like this?
def split_list(list, sub_list_size = 3):
sublists = []
for i in range(0, len(list), sub_list_size):
start = i
end = i + sub_list_size
sublists.append(list[start:end])
return sublists
# your list
mylist = [1,2,3,4,5,6,7,8, 9, 10, 11]
# your output
sublists = split_list(mylist)
print(sublists)
produces the following output
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]
The syntax list[start:end] will work even if end it is larger than the actual list size.
Hope this helps