5 Best Ways to Convert a List to a List of Lists Using a Step Value in Python

πŸ’‘ Problem Formulation: When working with lists in Python, you might encounter situations where you want to convert a flat list into a list of sublists, each of a specified length. For example, given the input list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and a step value of 3, the desired output would be [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]. This article explores different methods to achieve this transformation.

Method 1: Using List Comprehension

This method utilizes list comprehension to create the list of lists. It is Pythonic and concise, making use of Python’s slicing capabilities. The step value is used as the slicer increment within a range determined by the length of the original list.

Here’s an example:

def chunk_list(lst, step):
    return [lst[i:i + step] for i in range(0, len(lst), step)]

example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(chunk_list(example_list, 3))

Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

The chunk_list function takes a list and a step value. It generates a new list where each element is a sublist created by taking a slice of the original list from the current index i to i + step. This process is repeated until the list is completely sliced.

Method 2: Using the itertools.islice() Method

The itertools.islice() method is part of Python’s itertools module, which allows for efficient looping. This method can be used to slice the input list according to the step value without creating intermediate copies of the list. It is especially efficient for large lists.

Here’s an example:

from itertools import islice

def chunk_list_iter(lst, step):
    return [list(islice(lst, i, None, step)) for i in range(step)]

example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(chunk_list_iter(example_list, 3))

Output: [[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

The chunk_list_iter function uses islice to create sublists starting from each index within the step range. Each sublist takes every stepth element. Note that this approach differs from the previous one in how the sublists are constructed, which may or may not meet the user’s needs.

Method 3: Using a While Loop

This method involves a manual approach using a while loop, where you iteratively slice the list until all elements are included in the new list of lists. This is a more traditional, explicit way of handling list chunking.

Here’s an example:

def chunk_list_while(lst, step):
    chunks = []
    i = 0
    while i < len(lst):
        chunks.append(lst[i:i + step])
        i += step
    return chunks

example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(chunk_list_while(example_list, 3))

Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

The chunk_list_while function initializes an empty list to store the chunks. It then iterates over the original list, slicing it from the current index i to i + step and appending this sublist to the chunks list. The index i is incremented by the step value each iteration until the end of the list is reached.

Method 4: Using Recursion

Recursion can be used to achieve the same result by continuously breaking down the list into a head, which is a sublist of the desired step length, and a tail, which is the remainder of the list. This pattern continues until the tail is empty.

Here’s an example:

def chunk_list_recursive(lst, step):
    if not lst:
        return []
    return [lst[:step]] + chunk_list_recursive(lst[step:], step)

example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(chunk_list_recursive(example_list, 3))

Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

The chunk_list_recursive function bases its operation on two cases. If the list is empty, it returns an empty list. Otherwise, it constructs a new list with the first step elements as the head, and then recursively calls itself with the remainder of the list.

Bonus One-Liner Method 5: Using numpy.array_split()

For those who are not averse to using third-party libraries, NumPy offers the array_split() method which can handle splitting arrays into sublists of varying sizes, which is useful when the list size isn’t divisible by the step value.

Here’s an example:

import numpy as np

example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
step = 3
chunks = np.array_split(example_list, np.ceil(len(example_list)/step).astype(int))
chunks = [list(chunk) for chunk in chunks]
print(chunks)

Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

The numpy.array_split function is passed the original list and the number of desired splits, rounded up to ensure all elements are included. Each chunk is then converted back into a list, resulting in a list of lists.

Summary/Discussion

  • Method 1: List Comprehension. It is concise and Pythonic. However, list comprehensions may be less clear for beginners.
  • Method 2: itertools.islice(). This is memory efficient and good for large lists, but the resulting chunks are different from traditional chunking.
  • Method 3: While Loop. This method is clear and explicit, but it can be verbose compared to list comprehensions.
  • Method 4: Recursion. It’s elegant for small lists but can lead to a stack overflow error with very large lists.
  • Method 5: numpy.array_split(). One-liner and can handle uneven splits gracefully, but relies on NumPy which is an extra dependency if not already in use.