Build a key→value index from the right table, then walk left rows keeping only those whose key appears on both sides. With pandas, pd.merge(left, right, on='id') performs an inner join by default, dropping any row whose key is missing from either table.

By hand

With pandas

pd.merge(left, right, on='id') matches rows by the 'id' column and keeps only pairs with a key present in both DataFrames. The snapshot shows the merged columns, joined ids, and per-column values.

naive.py
left = [
    {'id': 1, 'name': 'al'},
    {'id': 2, 'name': 'bo'},
    {'id': 3, 'name': 'cy'},
]
right = [
    {'id': 1, 'score': 80},
    {'id': 3, 'score': 70},
    {'id': 4, 'score': 90},
]
right_idx = {}
for r in right:
    right_idx[r['id']] = r['score']
joined = []
for l in left:
    if l['id'] in right_idx:
        joined.append((l['name'], right_idx[l['id']]))
print('RESULT:', joined)
library.py
import pandas as pd
from dalib.display import set_display
set_display()

left = pd.DataFrame({'id': [1, 2, 3], 'name': ['al', 'bo', 'cy']})
right = pd.DataFrame({'id': [1, 3, 4], 'score': [80, 70, 90]})
merged = pd.merge(left, right, on='id')
print('columns:', merged.columns.tolist())
print('ids:', merged['id'].tolist())
print('names:', merged['name'].tolist())
print('scores:', merged['score'].tolist())
print('RESULT:', list(zip(merged['name'].tolist(), merged['score'].tolist())))
columns: ['id', 'name', 'score']
ids: [1, 3]
names: ['al', 'cy']
scores: [80, 70]
RESULT: [('al', 80), ('cy', 70)]

Implementation notes

  • pd.merge defaults to how='inner' — only rows with a matching key on both sides appear in the result. Row with id=2 (left-only) and id=4 (right-only) are both dropped.
  • The on= argument names the shared column used as the join key. If the key column has different names in each table, use left_on='id_left' and right_on='id_right' instead.
  • Row order in the result follows the left table's key order by default.
  • Cross-reference: inner-join-by-key (python-data-basics) for the pure-Python dict-index version.