Splitting a list into N parts of approximately equal length
This code is broken due to rounding errors. Do not use it!!!
assert len(chunkIt([1,2,3], 10)) == 10 # fails
Here's one that could work:
def chunkIt(seq, num):
avg = len(seq) / float(num)
out = []
last = 0.0
while last < len(seq):
out.append(seq[int(last):int(last + avg)])
last += avg
return out
Testing:
>>> chunkIt(range(10), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> chunkIt(range(11), 3)
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
>>> chunkIt(range(12), 3)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
How to divide a list into n equal parts, python
One-liner returning a list of lists, given a list and the chunk size:
>>> lol = lambda lst, sz: [lst[i:i+sz] for i in range(0, len(lst), sz)]
Testing:
>>> x = range(20, 36)
>>> print x
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
>>> lol(x, 4)
[[20, 21, 22, 23],
[24, 25, 26, 27],
[28, 29, 30, 31],
[32, 33, 34, 35]]
>>> lol(x, 7)
[[20, 21, 22, 23, 24, 25, 26],
[27, 28, 29, 30, 31, 32, 33],
[34, 35]]
Update:
I think the question is really asking is a function which, given a list and a number, returns a list containing $(number) lists, with the items of the original list evenly distributed. So your example of lol(x, 7) should really return [[20,21,22], [23,24,25], [26,27], [28,29], [30,31], [32,33], [34,35]]. – markrian
Well, in this case, you can try:
def slice_list(input, size):
input_size = len(input)
slice_size = input_size / size
remain = input_size % size
result = []
iterator = iter(input)
for i in range(size):
result.append([])
for j in range(slice_size):
result[i].append(iterator.next())
if remain:
result[i].append(iterator.next())
remain -= 1
return result
I'm sure this can be improved but I'm feeling lazy. :-)
>>> slice_list(x, 7)
[[20, 21, 22], [23, 24, 25],
[26, 27], [28, 29],
[30, 31], [32, 33],
[34, 35]]
How do I split a list into equally-sized chunks?
Here's a generator that yields evenly-sized chunks:
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
import pprint
pprint.pprint(list(chunks(range(10, 75), 10)))
[[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74]]
For Python 2, using xrange
instead of range
:
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in xrange(0, len(lst), n):
yield lst[i:i + n]
Below is a list comprehension one-liner. The method above is preferable, though, since using named functions makes code easier to understand. For Python 3:
[lst[i:i + n] for i in range(0, len(lst), n)]
For Python 2:
[lst[i:i + n] for i in xrange(0, len(lst), n)]
Splitting a list into N parts of approximately equal length
This code is broken due to rounding errors. Do not use it!!!
assert len(chunkIt([1,2,3], 10)) == 10 # fails
Here's one that could work:
def chunkIt(seq, num):
avg = len(seq) / float(num)
out = []
last = 0.0
while last < len(seq):
out.append(seq[int(last):int(last + avg)])
last += avg
return out
Testing:
>>> chunkIt(range(10), 3)
[[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>> chunkIt(range(11), 3)
[[0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
>>> chunkIt(range(12), 3)
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
Slicing a list into n nearly-equal-length partitions
def partition(lst, n):
division = len(lst) / float(n)
return [ lst[int(round(division * i)): int(round(division * (i + 1)))] for i in xrange(n) ]
>>> partition([1,2,3,4,5],5)
[[1], [2], [3], [4], [5]]
>>> partition([1,2,3,4,5],2)
[[1, 2, 3], [4, 5]]
>>> partition([1,2,3,4,5],3)
[[1, 2], [3, 4], [5]]
>>> partition(range(105), 10)
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], [32, 33, 34, 35, 36, 37, 38, 39, 40, 41], [42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52], [53, 54, 55, 56, 57, 58, 59, 60, 61, 62], [63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73], [74, 75, 76, 77, 78, 79, 80, 81, 82, 83], [84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94], [95, 96, 97, 98, 99, 100, 101, 102, 103, 104]]
Python 3 version:
def partition(lst, n):
division = len(lst) / n
return [lst[round(division * i):round(division * (i + 1))] for i in range(n)]
Divide a list into smaller lists
So, I hardly tried to make it in one line. Here is what I ended up with
import math
nb_classes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
N = 3
lists = [nb_classes[math.ceil(i): math.ceil(i + len(nb_classes) / N)] for i in (len(nb_classes) / N * j for j in range(N))]
print(lists) # [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]]
But this may be a little bit complicated, you just need to ceil your indexes
Splitting list into 2 parts, as equal to sum as possible
You could use a recursive algorithm and "brute force" partitioning of the list. Starting with a target difference of zero and progressively increasing your tolerance to the difference between the two lists:
def sumSplit(left,right=[],difference=0):
sumLeft,sumRight = sum(left),sum(right)
# stop recursion if left is smaller than right
if sumLeft<sumRight or len(left)<len(right): return
# return a solution if sums match the tolerance target
if sumLeft-sumRight == difference:
return left, right, difference
# recurse, brutally attempting to move each item to the right
for i,value in enumerate(left):
solution = sumSplit(left[:i]+left[i+1:],right+[value], difference)
if solution: return solution
if right or difference > 0: return
# allow for imperfect split (i.e. larger difference) ...
for targetDiff in range(1, sumLeft-min(left)+1):
solution = sumSplit(left, right, targetDiff)
if solution: return solution
# sumSplit returns the two lists and the difference between their sums
print(sumSplit([4,1,8,6])) # ([1, 8], [4, 6], 1)
print(sumSplit([5,3,2,2,2,1])) # ([2, 2, 2, 1], [5, 3], 1)
print(sumSplit([1,2,3,4,6])) # ([1, 3, 4], [2, 6], 0)
Related Topics
Django Media_Url and Media_Root
How to Use a Python Script in the Command Line Without Cd-Ing to Its Directory? Is It the Pythonpath
Calculate Cosine Similarity Given 2 Sentence Strings
Method Resolution Order (Mro) in New-Style Classes
Should You Always Favor Xrange() Over Range()
How to Get the Path of the Current Executed File in Python
How to Find the Exact Intersection of a Curve (As Np.Array) with Y==0
Rank Items in an Array Using Python/Numpy, Without Sorting Array Twice
How to Convert a String of Bytes into an Int
How to Generate Keyboard Events
How to Check If All Elements of a List Match a Condition
Why Do You Need Explicitly Have the "Self" Argument in a Python Method
Unicodedecodeerror: 'Utf8' Codec Can't Decode Byte 0Xa5 in Position 0: Invalid Start Byte
How to Capitalize the First Letter of Each Word in a String
Python Pandas Remove Duplicate Columns
What Are the 'Levels', 'Keys', and Names Arguments for in Pandas' Concat Function