Python
List
Programming
Data Structures
Code Example

Split a List into smaller lists of N size

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Splitting a list into fixed-size chunks is a common operation in batching, pagination, and parallel processing. The implementation is simple, but the right variant depends on whether you need an eager list result or lazy iteration for large datasets. A good utility also validates chunk size and handles edge cases consistently.

Basic Eager Chunking with Slicing

For small and medium lists, list slicing with a step is concise and readable.

python
1def chunk_list(items, n):
2    if n <= 0:
3        raise ValueError("n must be greater than zero")
4    return [items[i:i + n] for i in range(0, len(items), n)]
5
6
7data = [1, 2, 3, 4, 5, 6, 7]
8print(chunk_list(data, 3))
9# [[1, 2, 3], [4, 5, 6], [7]]

This creates all chunks in memory at once, which is fine for typical API payload sizes and UI data lists.

Lazy Chunking with Generators

For very large inputs or streaming pipelines, yield chunks lazily to reduce memory pressure.

python
1def chunk_iter(items, n):
2    if n <= 0:
3        raise ValueError("n must be greater than zero")
4    for i in range(0, len(items), n):
5        yield items[i:i + n]
6
7
8data = list(range(1, 21))
9for part in chunk_iter(data, 6):
10    print(part)

This pattern is useful when each chunk is processed and discarded immediately.

Chunking Generic Iterables

If input is not a list but any iterable, you can chunk without indexing by using itertools.islice.

python
1from itertools import islice
2
3
4def chunk_any_iterable(iterable, n):
5    if n <= 0:
6        raise ValueError("n must be greater than zero")
7    it = iter(iterable)
8    while True:
9        batch = list(islice(it, n))
10        if not batch:
11            break
12        yield batch
13
14
15def number_stream():
16    for i in range(1, 11):
17        yield i
18
19
20print(list(chunk_any_iterable(number_stream(), 4)))
21# [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

This is a flexible utility for database cursors, file streams, and queue consumers.

Real-World Use Cases

  • Batch inserts to databases.
  • Rate-limited API calls in groups.
  • Parallel job dispatch where each worker receives a chunk.
  • Pagination pre-processing for templates or reports.

When integrating with external systems, choose chunk size based on service limits and timeout behavior, not only code convenience.

Handling Edge Cases Deliberately

Define behavior once and document it:

  • n <= 0 should raise ValueError.
  • empty list should return empty result.
  • list smaller than n should return one chunk containing all elements.

Quick checks:

python
1assert chunk_list([], 3) == []
2assert chunk_list([1, 2], 5) == [[1, 2]]
3
4try:
5    chunk_list([1, 2, 3], 0)
6except ValueError:
7    pass
8else:
9    raise AssertionError("Expected ValueError for n=0")

These tests prevent subtle regressions in utility functions used throughout a codebase.

Performance Notes

Time complexity is linear in input size for all standard chunking methods. Memory profile depends on strategy:

  • eager list comprehension stores every chunk at once.
  • generator approach stores one chunk at a time.

If chunking appears in a hot path, measure end-to-end throughput including downstream processing. Often the chunk utility itself is not the bottleneck.

Common Pitfalls

  • Allowing zero or negative chunk size and producing confusing behavior.
  • Building all chunks eagerly for huge datasets and causing memory spikes.
  • Assuming iterable inputs support slicing and index operations.
  • Forgetting to process the final partial chunk.
  • Choosing arbitrary chunk sizes without considering external service limits.

Summary

  • List slicing with step is the clean default for normal workloads.
  • Generator chunking is better for large data and streaming flows.
  • Validate chunk size and document edge-case behavior.
  • Use iterable-safe chunking for non-list sources.
  • Base chunk size on system limits and performance measurements.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms