Python
dictionaries
key-value pairs
data manipulation
programming

Return first N keyvalue pairs from dict

Master System Design with Codemia

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

Introduction

In modern Python, dictionaries preserve insertion order, so returning the first N key-value pairs is straightforward. The important part is defining what first means in your context: insertion order, sorted order, or stream order. Once that is clear, implementation is mostly about correctness and edge-case handling.

Insertion Order Solution with itertools.islice

If you want the first N entries exactly as inserted, use islice on dict.items.

python
1from itertools import islice
2
3
4def first_n_pairs(d: dict, n: int) -> dict:
5    if n <= 0:
6        return {}
7    return dict(islice(d.items(), n))
8
9
10sample = {"a": 1, "b": 2, "c": 3, "d": 4}
11print(first_n_pairs(sample, 2))

This avoids building a full list of items before slicing, which is useful for larger dictionaries.

You can also return tuples instead of a dictionary if duplicate keys must remain visible in upstream data transformations.

python
def first_n_item_tuples(d: dict, n: int):
    return list(islice(d.items(), max(n, 0)))

Sorted-Key Interpretation When Required

Sometimes first means alphabetical or numeric key order, not insertion order.

python
1
2def first_n_sorted_by_key(d: dict, n: int) -> dict:
3    if n <= 0:
4        return {}
5    pairs = sorted(d.items(), key=lambda kv: kv[0])
6    return dict(pairs[:n])
7
8
9sample = {"b": 2, "a": 1, "d": 4, "c": 3}
10print(first_n_sorted_by_key(sample, 3))

Be explicit in function naming so callers understand ordering semantics.

Streaming and Large Data Considerations

If data is produced incrementally, you may not need to materialize a full dictionary first. Consume first N pairs directly from an iterator.

python
1from itertools import islice
2
3
4def first_n_from_pairs_iter(pairs_iter, n: int) -> dict:
5    return dict(islice(pairs_iter, max(n, 0)))
6
7
8pairs = ((str(i), i * i) for i in range(1_000_000))
9small = first_n_from_pairs_iter(pairs, 5)
10print(small)

This pattern keeps memory use low and fits ETL-style pipelines.

Defensive Input Handling

In utility functions used across teams, validate inputs early.

python
1
2def safe_first_n_pairs(d: dict, n: int) -> dict:
3    if not isinstance(d, dict):
4        raise TypeError("d must be a dict")
5    if not isinstance(n, int):
6        raise TypeError("n must be an int")
7    if n < 0:
8        raise ValueError("n must be non-negative")
9    return dict(islice(d.items(), n))

Defensive checks help avoid subtle runtime bugs when data contracts drift.

Testing Scenarios You Should Cover

At minimum, test:

  • n == 0,
  • n < len(d),
  • n == len(d),
  • n > len(d),
  • empty dictionary,
  • non-string keys if sorting is used.

Example with simple assertions:

python
assert first_n_pairs({}, 3) == {}
assert first_n_pairs({"x": 1}, 0) == {}
assert first_n_pairs({"x": 1, "y": 2}, 5) == {"x": 1, "y": 2}

Clear tests make ordering assumptions visible and prevent regressions during refactors.

Practical API Design Patterns

If this logic lives in a library, expose separate helpers for insertion-order and sorted-order behavior instead of one overloaded function with hidden flags. Explicit APIs reduce misuse.

Example:

python
1def first_n_insertion(d: dict, n: int) -> dict:
2    return first_n_pairs(d, n)
3
4def first_n_sorted(d: dict, n: int) -> dict:
5    return first_n_sorted_by_key(d, n)

This makes call sites self-documenting, which helps in large codebases where assumptions about ordering differ between teams.

For JSON API responses, remember that object key order may be preserved by many runtimes but should not be treated as a universal protocol guarantee unless your consumers explicitly rely on it and tests enforce it.

Common Pitfalls

  • Assuming insertion order behavior in very old Python runtimes.
  • Mixing insertion-order and sorted-order semantics in one helper.
  • Returning dictionary output when caller needs duplicate key entries preserved from a pair stream.
  • Forgetting to handle negative N values.
  • Sorting keys of mixed incomparable types without a custom strategy.

Summary

  • Use islice(d.items(), n) for insertion-order first N retrieval.
  • Use explicit sorting only when sorted-order behavior is required.
  • Validate input contracts in shared utility functions.
  • Prefer iterator-first patterns for large streaming data pipelines.
  • Keep tests focused on ordering and edge-case semantics.

Course illustration
Course illustration

All Rights Reserved.