ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 18

  1. Blog

zip vs Index Pairing: Loop Lab

Aditya Challa·30 September 2026·4 min read

Summary
On this page
  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — consume N=100 000 / 1 000 000 (p50)
  5. Materialize `list(...)` N=100 000
  6. Unequal lengths & 3-way
  7. Reading it
  8. Why index sometimes “wins” on huge `list(zip)`
  9. strict=True as production default
  10. Pitfalls
  11. When to pick what
  12. Reproduce
  13. Closing

Intro — what this post promises

Pairing two sequences: is zip faster than for i in range(n): (a[i], b[i]), and what does strict=True cost? This lab times materialize (list(zip)) and consume loops on Linux localhost.

Related links:

  • itertools chain vs flatten localhost lab
  • functools partial vs lambda localhost lab
  • itertools vs python loops localhost lab
  • nlargest vs sorted slice localhost lab
  • array vs list ints localhost lab
  • statistics vs manual mean localhost lab
  • bisect vs linear lookup localhost lab
  • perf_counter vs time localhost lab

Lab honesty (1 Oct 2026 IST): Python 3.13.5. One op = one pair. Affiliates: 0. zip truncates to the shorter input; strict=True errors on length mismatch.

Verdict up front (N=100 000 consume): zip ~26.8M/s vs index ~23.8M (~1.13×); list(zip) ~1.15× index comprehension. strict=True ≈ plain zip on equal-length consume (~0.98×). Prefer zip for clarity; index when you already need i.


Arms

ArmPattern
list(zip(a,b))materialize pairs
list(zip(..., strict=True))length-checked zip
index comprehension[(a[i], b[i]) for i in range(n)]
index append loopmanual append
consume zip / indexsum x+y without list of tuples
enumerate(zip(...))index + pair

Lab topology

N in {1000, 10000, 100000, 1000000}
also unequal truncate + 3-way zip consume

Script: lab-evidence/71-zip-vs-index-pairing/results/run_lab.py.


Lead table — consume N=100 000 / 1 000 000 (p50)

ArmN=100k ops/sN=1M ops/s
zip26,785,95326,827,121
zip strict27,347,67526,747,626
index23,798,49723,709,280
enumerate(zip)14,214,23714,218,640

Index alone beat enumerate(zip) by ~1.7× — do not pay enumerate if you only need the parallel elements.


Materialize list(...) N=100 000

Armops/sns/op
zip15,927,09262.8
zip strict18,122,22955.2
index comp13,894,45172.0
index append13,721,41572.9

At N=1M materialize, index comp edged zip (zip÷index ~0.79×) — allocation/GC noise shows up; consume path still favored zip.


Unequal lengths & 3-way

Armops/s
zip truncate (shorter)18,035,546
index min(len)15,050,812
consume zip319,816,798
consume index317,650,335

zip truncate ~1.20× index-min; 3-way zip ~1.12× index3.


Reading it

  • zip is the default pairing API — readable and usually as fast or faster on consume.
  • strict=True is nearly free on equal lengths here — use it to catch bugs.
  • Need the index anyway — range/enumerate on one sequence; avoid enumerate(zip) unless you need both.
  • Materialize only if you need a list of pairs — otherwise iterate zip directly.

Why index sometimes “wins” on huge list(zip)

Building millions of tuple objects dominates. Small timing flips between zip and index comps at N=1M are about allocator behavior, not a reason to rewrite clear zip loops. Optimize the consume shape you actually run in production.


strict=True as production default

Equal-length zip is the common case; the bug is silently dropping a tail when lengths drift after a refactor. On this box the consume overhead of strict=True was noise (~1.00×). Prefer zip(a, b, strict=True) in new code unless you intentionally want truncation — and if you do, comment why.


Pitfalls

  1. Silent truncation with plain zip on unequal inputs — prefer strict=True.
  2. enumerate(zip(a,b)) when i unused — extra work.
  3. Building list(zip(...)) just to iterate once — waste.
  4. Assuming index is always slower — microbenches vary; API clarity still favors zip.

When to pick what

NeedPrefer
Pair / parallel iteratezip
Assert equal lengthszip(..., strict=True)
Need index + one sequenceenumerate(seq)
Need index into multiple listsrange(n) or enumerate + index

Reproduce

python3 lab-evidence/71-zip-vs-index-pairing/results/run_lab.py

Evidence: /workspace/lab-evidence/71-zip-vs-index-pairing/results/.


Closing

zip for pairing; strict for safety; index when you need i. On this box N=100 k consume zip led index by ~1.13×, strict matched zip, and enumerate(zip) trailed bare index by ~1.7×. Write zip first; reach for indices when the algorithm needs them.

zipzip strictindex pairingenumeratepythonlocalhost labsrepairing

Lab evidence

What I found running this

Lab 1 Oct 2026 IST. Python 3.13.5. N=100k consume zip 26.8M vs index 23.8M (~1.13x); list(zip) vs index-comp ~1.15x; strict ≈ zip on consume. Affiliates: 0. Evidence: lab-evidence/71-zip-vs-index-pairing/.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 17

    platform vs os.uname Inventory: Localhost Lab

    Hands-on platform.platform vs os.uname host inventory lab: real ops/s plus cache notes, measured on Linux localhost today in this hands-on lab for SREs.

    1 Oct 2026

  • Plate 50

    signal vs threading.Event Wakeup: Localhost Lab

    Hands-on signal SIGUSR1 vs threading.Event wakeup lab: real p50 latency in microseconds, measured on Linux localhost today in this hands-on lab for SREs.

    1 Oct 2026

  • Plate 76

    cmath vs math.hypot Magnitudes: Localhost Lab

    Hands-on cmath vs math.hypot magnitude ops lab: real ops/s for abs, polar, and phase, measured on Linux localhost today in this hands-on lab for SREs.

    1 Oct 2026

On this page

  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — consume N=100 000 / 1 000 000 (p50)
  5. Materialize `list(...)` N=100 000
  6. Unequal lengths & 3-way
  7. Reading it
  8. Why index sometimes “wins” on huge `list(zip)`
  9. strict=True as production default
  10. Pitfalls
  11. When to pick what
  12. Reproduce
  13. Closing
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove