Python
List Comparison
Coding
Programming Tips
Data Structures

Checking if List contains all items from another list

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Checking whether one Python list contains all items from another is simple only after you define what "contains" means. Sometimes duplicates matter, sometimes order matters, and sometimes you only care about set membership. The correct implementation depends on that rule, and different rules lead to different algorithms.

Case 1: Membership Only, Duplicates Do Not Matter

If you only need to know whether every distinct item from one list exists in another, sets are the clearest option.

python
1def contains_all(container, required):
2    return set(required).issubset(set(container))
3
4
5print(contains_all([1, 2, 3, 4], [2, 4]))
6print(contains_all([1, 2, 3, 4], [2, 5]))

This is efficient and readable, but it ignores duplicate counts.

Case 2: Duplicates Matter

If [1, 1, 2] should not be considered contained by [1, 2], use collections.Counter.

python
1from collections import Counter
2
3
4def contains_all_with_counts(container, required):
5    return not (Counter(required) - Counter(container))
6
7
8print(contains_all_with_counts([1, 1, 2, 3], [1, 2]))
9print(contains_all_with_counts([1, 2, 3], [1, 1]))

This compares multiplicity, which is usually the correct rule for inventory-like or occurrence-sensitive problems.

Case 3: Straightforward Readability With all

For small lists, a direct all check is perfectly fine.

python
1def contains_all_simple(container, required):
2    return all(item in container for item in required)
3
4
5print(contains_all_simple(["a", "b", "c"], ["a", "c"]))

This is readable, but it may become slower on large lists because each membership test is linear for plain lists.

Order-Sensitive Variant

If the order of appearance matters, you are solving a different problem. You may need subsequence logic rather than simple containment.

python
1def is_subsequence(container, required):
2    it = iter(container)
3    return all(any(x == item for x in it) for item in required)
4
5
6print(is_subsequence([1, 2, 3, 4], [2, 4]))
7print(is_subsequence([1, 2, 3, 4], [4, 2]))

This checks whether required items appear in the same relative order.

Performance Tradeoffs

The right choice depends on input size and semantics:

  • 'all(item in list ...) is fine for small inputs.'
  • 'set-based checks are good for large membership-only comparisons.'
  • 'Counter is best when duplicate counts matter.'

Choosing set for everything is a mistake if duplicates carry meaning.

Custom Objects Need Equality Rules

If lists contain custom objects, containment depends on how equality is defined. For dataclasses or classes, make sure __eq__ behaves the way your domain expects.

python
1from dataclasses import dataclass
2
3
4@dataclass(frozen=True)
5class User:
6    id: int
7
8
9users = [User(1), User(2), User(3)]
10required = [User(2), User(3)]
11
12print(all(item in users for item in required))

Without well-defined equality, containment checks may produce surprising results.

Normalize Inputs When Needed

Containment checks can also fail because the two lists use different data formats, such as mixed casing or whitespace.

python
1def normalized_contains_all(container, required):
2    left = {item.strip().lower() for item in container}
3    right = {item.strip().lower() for item in required}
4    return right.issubset(left)
5
6
7print(normalized_contains_all(["A ", "b", "C"], ["a", "c"]))

This is a domain rule, not a generic default, but it is common in user-facing string comparisons.

Practical Decision Guide

Choose the approach by business rule:

  • Distinct membership uses set.
  • Multiplicity-aware membership uses Counter.
  • Ordered inclusion uses subsequence logic.
  • Very small lists can use all(...) for clarity.

Make the rule explicit in the function name so future readers do not have to guess.

Common Pitfalls

  • Using sets when duplicate counts actually matter.
  • Using list membership loops on very large inputs without thinking about cost.
  • Forgetting that order-sensitive checks are a different problem.
  • Assuming custom objects compare the way business logic expects.
  • Naming helper functions too vaguely, such as contains_all, when semantics are more specific.

Summary

  • There is no single best containment check until you define the exact rule.
  • Use set.issubset when only distinct membership matters.
  • Use Counter when duplicates matter.
  • Use subsequence logic when order matters.
  • Name your helper by semantics so the implementation stays defensible.

Course illustration
Course illustration

All Rights Reserved.