Python
Shuffling
List Manipulation
Python Programming
Coding Tutorial

Specific shuffling list in Python

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

Python's random.shuffle() randomizes a list in place, but many real-world scenarios require specific shuffling patterns — reproducible shuffles with a seed, shuffling without modifying the original, shuffling groups of elements together, or interleaving lists in a specific pattern. This article covers standard shuffling, seeded shuffles, partial shuffles, group-preserving shuffles, and custom shuffle algorithms.

Basic Shuffle (In-Place)

python
1import random
2
3items = [1, 2, 3, 4, 5]
4random.shuffle(items)
5print(items)  # e.g., [3, 1, 5, 2, 4] — different each run

random.shuffle() modifies the list in place and returns None. It uses the Fisher-Yates algorithm, which produces a uniform distribution of all permutations.

Shuffle Without Modifying the Original

Use random.sample() to get a shuffled copy:

python
1original = [1, 2, 3, 4, 5]
2shuffled = random.sample(original, len(original))
3
4print(original)  # [1, 2, 3, 4, 5] — unchanged
5print(shuffled)   # e.g., [4, 2, 5, 1, 3]

Or copy first, then shuffle:

python
shuffled = original.copy()
random.shuffle(shuffled)

Reproducible Shuffle (Seeded)

Set a seed so the shuffle produces the same result every time:

python
1random.seed(42)
2items = [1, 2, 3, 4, 5]
3random.shuffle(items)
4print(items)  # Always [1, 4, 2, 5, 3] with seed 42
5
6# Reset and shuffle again — same result
7random.seed(42)
8items = [1, 2, 3, 4, 5]
9random.shuffle(items)
10print(items)  # [1, 4, 2, 5, 3] again

Useful for testing, reproducible experiments, and debugging.

Shuffle with Custom Random Generator

Use an independent Random instance to avoid affecting global state:

python
1rng = random.Random(42)
2items = [1, 2, 3, 4, 5]
3rng.shuffle(items)
4print(items)  # Deterministic, independent of other random calls

This is important in multithreaded code or when you need multiple independent random streams.

Partial Shuffle (Shuffle First N Elements Only)

Shuffle only a portion of the list:

python
1def partial_shuffle(lst, n):
2    """Shuffle only the first n elements."""
3    subset = lst[:n]
4    random.shuffle(subset)
5    return subset + lst[n:]
6
7items = [1, 2, 3, 4, 5, 6, 7, 8]
8result = partial_shuffle(items, 4)
9print(result)  # e.g., [3, 1, 4, 2, 5, 6, 7, 8] — last 4 unchanged

Group-Preserving Shuffle

Shuffle groups of elements together (e.g., keep pairs intact):

python
1def shuffle_groups(lst, group_size):
2    """Shuffle list in chunks of group_size."""
3    groups = [lst[i:i + group_size] for i in range(0, len(lst), group_size)]
4    random.shuffle(groups)
5    return [item for group in groups for item in group]
6
7items = [1, 2, 3, 4, 5, 6]
8result = shuffle_groups(items, 2)
9print(result)  # e.g., [5, 6, 1, 2, 3, 4] — pairs stay together

Constrained Shuffle (No Element in Original Position)

A derangement ensures no element remains in its original position:

python
1def derangement(lst):
2    """Shuffle such that no element stays in its original position."""
3    result = lst.copy()
4    while True:
5        random.shuffle(result)
6        if all(result[i] != lst[i] for i in range(len(lst))):
7            return result
8
9items = [1, 2, 3, 4, 5]
10result = derangement(items)
11print(result)  # No element at its original index

This brute-force approach is efficient for small lists. For large lists, use the Sattolo algorithm.

Weighted Shuffle

Shuffle with bias — elements with higher weights appear earlier:

python
1items = ["A", "B", "C", "D"]
2weights = [10, 1, 5, 3]
3
4# Weighted shuffle using random.choices (with replacement) or sorted approach
5weighted_order = sorted(
6    range(len(items)),
7    key=lambda i: -random.random() ** (1.0 / weights[i])
8)
9result = [items[i] for i in weighted_order]
10print(result)  # "A" tends to appear first due to highest weight

Interleave Two Lists

Merge two lists in alternating order (a specific "shuffle" pattern):

python
1def interleave(a, b):
2    """Alternate elements from two lists."""
3    result = []
4    for x, y in zip(a, b):
5        result.extend([x, y])
6    # Append remaining elements from the longer list
7    result.extend(a[len(b):])
8    result.extend(b[len(a):])
9    return result
10
11list_a = [1, 2, 3]
12list_b = ["a", "b", "c"]
13print(interleave(list_a, list_b))  # [1, 'a', 2, 'b', 3, 'c']

Shuffle a Dictionary's Values

Shuffle values while keeping keys intact:

python
1d = {"a": 1, "b": 2, "c": 3, "d": 4}
2
3keys = list(d.keys())
4values = list(d.values())
5random.shuffle(values)
6
7shuffled_dict = dict(zip(keys, values))
8print(shuffled_dict)  # e.g., {'a': 3, 'b': 1, 'c': 4, 'd': 2}

Common Pitfalls

  • Assigning the return value of shuffle(): random.shuffle() returns None and modifies the list in place. result = random.shuffle(items) sets result to None. Use random.sample(items, len(items)) for a returned shuffled copy.
  • Shuffling immutable sequences: random.shuffle() requires a mutable sequence. Passing a tuple or string raises TypeError. Convert to a list first: list("hello"), then shuffle.
  • Global seed affecting other random calls: random.seed(42) affects all subsequent calls to the random module. Use random.Random(42) for an independent generator that does not interfere with other random operations.
  • Shuffling a generator: random.shuffle() needs indexed access (__getitem__). Generators and iterators do not support this. Convert to a list first: items = list(generator).
  • Non-uniform shuffle from a bad algorithm: Implementing shuffle manually (e.g., swapping each element with a random position from the entire array) produces a biased distribution. Always use Fisher-Yates (which random.shuffle implements) or random.sample().

Summary

  • random.shuffle(lst) shuffles in place (returns None) using the Fisher-Yates algorithm
  • random.sample(lst, len(lst)) returns a new shuffled list without modifying the original
  • Use random.seed(n) or random.Random(n) for reproducible shuffles
  • Chunk the list for group-preserving shuffles, or loop until a derangement for constrained shuffles
  • Use weighted random keys for priority-biased shuffling
  • Always use random.shuffle() or random.sample() instead of custom swap algorithms to ensure uniform distribution

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
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms