Python
dictionaries
lists
check value
data structures

Check if value already exists within list of dictionaries 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

A list of dictionaries is a common Python shape for API responses, configuration records, and in-memory datasets. Checking whether a value already exists sounds simple, but the right method depends on lookup frequency, data size, and whether you check one key or many fields. Choosing the correct pattern avoids unnecessary loops and keeps code readable.

Basic Membership Check by Key

For one-time checks, any with a generator expression is clear and efficient.

python
1users = [
2    {"id": 1, "email": "[email protected]"},
3    {"id": 2, "email": "[email protected]"},
4    {"id": 3, "email": "[email protected]"},
5]
6
7target_email = "[email protected]"
8exists = any(row.get("email") == target_email for row in users)
9
10print(exists)

any short-circuits, so iteration stops at the first match.

Return the Matching Record

Sometimes you need the item itself, not just a boolean.

python
1users = [
2    {"id": 1, "email": "[email protected]"},
3    {"id": 2, "email": "[email protected]"},
4]
5
6target_email = "[email protected]"
7match = next((row for row in users if row.get("email") == target_email), None)
8
9print(match)

Using next with a default avoids StopIteration errors.

Case-Insensitive and Normalized Checks

Real-world data often has casing and whitespace differences. Normalize before comparison.

python
1records = [
2    {"city": "Toronto"},
3    {"city": "new york"},
4    {"city": "  Berlin  "},
5]
6
7def normalize(value: str) -> str:
8    return value.strip().casefold()
9
10target = "berlin"
11exists = any(normalize(r.get("city", "")) == normalize(target) for r in records)
12print(exists)

Without normalization, logically equivalent values can be missed.

Multiple Conditions

If uniqueness depends on more than one field, compare tuples.

python
1orders = [
2    {"user_id": 10, "product_id": 7, "status": "open"},
3    {"user_id": 10, "product_id": 9, "status": "open"},
4]
5
6candidate = {"user_id": 10, "product_id": 7}
7exists = any(
8    (row.get("user_id"), row.get("product_id")) ==
9    (candidate["user_id"], candidate["product_id"])
10    for row in orders
11)
12
13print(exists)

This keeps matching logic explicit and easy to test.

Speeding Up Repeated Lookups

For many repeated checks, prebuild a set index for average constant-time membership.

python
1users = [
2    {"id": 1, "email": "[email protected]"},
3    {"id": 2, "email": "[email protected]"},
4    {"id": 3, "email": "[email protected]"},
5]
6
7email_index = {row["email"] for row in users}
8
9print("[email protected]" in email_index)
10print("[email protected]" in email_index)

If records change frequently, rebuild or maintain the index as part of update operations.

Handling Missing Keys Safely

Data from external sources may miss expected keys. Prefer dict.get with sensible defaults.

python
1rows = [
2    {"id": 1, "email": "[email protected]"},
3    {"id": 2},
4]
5
6exists = any(row.get("email") == "[email protected]" for row in rows)
7print(exists)

Direct indexing like row["email"] would raise KeyError on incomplete rows.

Function Utility Pattern

Wrap your lookup logic in a utility to avoid repeating custom loops.

python
1def value_exists(rows, key, target):
2    return any(row.get(key) == target for row in rows)
3
4items = [
5    {"sku": "A-100"},
6    {"sku": "B-200"},
7]
8
9print(value_exists(items, "sku", "B-200"))

Utility functions improve consistency and make unit tests simpler.

Complexity and Memory Tradeoffs

Loop-based checks are linear in time and use minimal extra memory. Pre-indexed set lookups are faster for repeated queries but require memory for the index and maintenance logic for updates.

General rule:

  • One or few checks: use any.
  • Frequent checks on stable data: build a set or dictionary index.

This keeps performance and code complexity balanced. If lookup patterns evolve, profile before rewriting data structures.

Common Pitfalls

  • Looping manually with flags and break logic everywhere. Fix by using any or next patterns.
  • Using direct key indexing on partial data. Fix by using get with defaults.
  • Ignoring normalization requirements for text comparisons. Fix by applying strip and case folding.
  • Recomputing expensive lookups in tight loops. Fix by prebuilding set indexes.
  • Mixing boolean existence checks and record retrieval logic. Fix by separating helper functions for each use case.

Summary

  • any is the clearest approach for one-off existence checks.
  • Use next when you need the matching dictionary, not only a boolean.
  • Normalize text fields to avoid false negatives.
  • Build indexes for high-volume repeated lookups.
  • Choose method based on data scale and update frequency.

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