Python
list-shuffling
data-structures
programming
list-manipulation

Shuffle two list at once with same order

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

When two lists contain aligned data, such as features and labels, they must be shuffled with the same permutation. Shuffling them independently destroys that alignment and silently corrupts the data, which makes this a correctness problem, not just a convenience issue.

The Wrong Approach

This is what not to do:

python
1import random
2
3texts = ["a", "b", "c", "d"]
4labels = [0, 1, 0, 1]
5
6random.shuffle(texts)
7random.shuffle(labels)
8
9print(texts)
10print(labels)

After this runs, there is no guarantee that each text still matches the correct label.

Zip, Shuffle, Unzip

For two lists, the simplest correct pattern is to zip them together, shuffle once, and unzip them afterward.

python
1import random
2
3texts = ["a", "b", "c", "d"]
4labels = [0, 1, 0, 1]
5
6pairs = list(zip(texts, labels))
7random.Random(42).shuffle(pairs)
8
9texts_shuffled, labels_shuffled = zip(*pairs)
10
11print(list(texts_shuffled))
12print(list(labels_shuffled))

This works because each pair stays together during the shuffle.

Shared Index Permutation

If you have more than two aligned lists or arrays, generate one shuffled index order and apply it everywhere.

python
1import random
2
3features = ["a", "b", "c", "d"]
4labels = [0, 1, 0, 1]
5weights = [0.2, 0.8, 0.3, 0.9]
6
7indices = list(range(len(features)))
8random.Random(42).shuffle(indices)
9
10features_s = [features[i] for i in indices]
11labels_s = [labels[i] for i in indices]
12weights_s = [weights[i] for i in indices]
13
14print(features_s)
15print(labels_s)
16print(weights_s)

This scales better and makes it obvious that one permutation is being reused consistently.

In-Place Pair Shuffling

If you want to keep the paired structure, you can simply continue working with the zipped list after shuffling.

python
1import random
2
3pairs = [("a", 0), ("b", 1), ("c", 0), ("d", 1)]
4random.shuffle(pairs)
5
6for text, label in pairs:
7    print(text, label)

This is often the best option if the two-list representation is only temporary anyway.

Reproducibility Matters

In machine learning and testing, use a dedicated random generator with a seed rather than the process-wide global random state.

python
1import random
2
3items = list(zip(["a", "b", "c"], [1, 2, 3]))
4rng = random.Random(123)
5rng.shuffle(items)
6
7print(items)

This makes the shuffle deterministic and easier to debug.

NumPy Arrays Need the Same Idea

If your data lives in NumPy arrays rather than Python lists, the principle is unchanged: create one permutation and apply it to every aligned array.

python
1import numpy as np
2
3x = np.array(["a", "b", "c", "d"])
4y = np.array([0, 1, 0, 1])
5
6rng = np.random.default_rng(42)
7perm = rng.permutation(len(x))
8
9print(x[perm])
10print(y[perm])

This is usually better than converting arrays to lists just to shuffle them.

Length Mismatch Should Fail Fast

Before shuffling, ensure the lists are actually aligned by length.

python
1def shuffle_together(left, right, seed=None):
2    if len(left) != len(right):
3        raise ValueError("Lists must have the same length")
4
5    pairs = list(zip(left, right))
6    random.Random(seed).shuffle(pairs)
7    return map(list, zip(*pairs)) if pairs else ([], [])

Validation matters because a length mismatch is already a data bug before shuffling begins.

Common Pitfalls

The biggest pitfall is calling random.shuffle() separately on each list. Even if both lists are shuffled "randomly," they are almost certainly no longer aligned.

Another issue is forgetting that zip() returns tuples, not lists. That is usually fine, but some code expects mutable lists after the shuffle.

Developers also forget to seed the random generator when reproducibility matters for tests or model training.

Finally, if the lists may be empty, be careful with zip(*pairs) because unzipping an empty list of pairs needs special handling.

Summary

  • Keep aligned data under one shared permutation when shuffling.
  • For two lists, zip, shuffle, and unzip is the simplest solution.
  • For many aligned structures, shuffle indices once and reuse them everywhere.
  • Use a seeded random generator when you need reproducible results.
  • Validate list lengths before shuffling so data bugs fail early.

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

All Rights Reserved.