Build a label-to-index map from a parallel labels list, then look up rows by string key. With pandas, a DataFrame can carry a named index, and df.loc selects rows by those labels directly — no manual mapping needed.

By hand

Loop over labels to build label_to_idx (label → integer position). Then loop over the target keys, resolve each to a position, and pull the row from records.

naive.py
Replay: real traced execution (multi-file project)
# trace: ignore records
labels = ['p', 'q', 'r', 's']
records = [
    {'name': 'al', 'age': 20},
    {'name': 'bo', 'age': 25},
    {'name': 'cy', 'age': 22},
    {'name': 'di', 'age': 28},
]
label_to_idx = {}
for i in range(len(labels)):
    label_to_idx[labels[i]] = i
keys = ['p', 'r']
names = []
for k in keys:
    idx = label_to_idx[k]
    names.append(records[idx]['name'])
print('RESULT:', names)
  1. labels ← ['p', 'q', 'r', 's']

    1# trace: ignore records2labels = ['p', 'q', 'r', 's']3records = [
    values this step['p', 'q', 'r', 's']labels
  2. {'name': 'al', 'age': 20},

    3records = [4    {'name': 'al', 'age': 20},5    {'name': 'bo', 'age': 25},
  3. {'name': 'bo', 'age': 25},

    4{'name': 'al', 'age': 20},5{'name': 'bo', 'age': 25},6{'name': 'cy', 'age': 22},
  4. {'name': 'cy', 'age': 22},

    5{'name': 'bo', 'age': 25},6{'name': 'cy', 'age': 22},7{'name': 'di', 'age': 28},
  5. {'name': 'di', 'age': 28},

    6    {'name': 'cy', 'age': 22},7    {'name': 'di', 'age': 28},8]
  6. records = [

    2labels = ['p', 'q', 'r', 's']3records = [4    {'name': 'al', 'age': 20},
  7. label_to_idx ← {}

    8]9label_to_idx = {}10for i in range(len(labels)):
    values this step{}label_to_idx
  8. i ← 0

    9label_to_idx = {}10for i in range(len(labels)):11    label_to_idx[labels[i]] = i
    values this step0i
  9. label_to_idx ← {'p': 0}

    10for i in range(len(labels)):11    label_to_idx[labels[i]] = i12keys = ['p', 'r']
    values this step{} {'p': 0}label_to_idx
  10. i ← 1

    9label_to_idx = {}10for i in range(len(labels)):11    label_to_idx[labels[i]] = i
    values this step0 1i
  11. label_to_idx ← {'p': 0, 'q': 1}

    10for i in range(len(labels)):11    label_to_idx[labels[i]] = i12keys = ['p', 'r']
    values this step{'p': 0} {'p': 0, 'q': 1}label_to_idx
  12. i ← 2

    9label_to_idx = {}10for i in range(len(labels)):11    label_to_idx[labels[i]] = i
    values this step1 2i
  13. label_to_idx ← {'p': 0, 'q': 1, 'r': 2}

    10for i in range(len(labels)):11    label_to_idx[labels[i]] = i12keys = ['p', 'r']
    values this step{'p': 0, 'q': 1} {'p': 0, 'q': 1, 'r': 2}label_to_idx
  14. i ← 3

    9label_to_idx = {}10for i in range(len(labels)):11    label_to_idx[labels[i]] = i
    values this step2 3i
  15. label_to_idx ← {'p': 0, 'q': 1, 'r': 2, 's': 3}

    10for i in range(len(labels)):11    label_to_idx[labels[i]] = i12keys = ['p', 'r']
    values this step{'p': 0, 'q': 1, 'r': 2} {'p': 0, 'q': 1, 'r': 2, 's': 3}label_to_idx
  16. for i in range(len(labels)):

    9label_to_idx = {}10for i in range(len(labels)):11    label_to_idx[labels[i]] = i
  17. keys ← ['p', 'r']

    11    label_to_idx[labels[i]] = i12keys = ['p', 'r']13names = []
    values this step['p', 'r']keys
  18. names ← []

    12keys = ['p', 'r']13names = []14for k in keys:
    values this step[]names
  19. k ← 'p'

    13names = []14for k in keys:15    idx = label_to_idx[k]
    values this step'p'k
  20. idx ← 0

    14for k in keys:15    idx = label_to_idx[k]16    names.append(records[idx]['name'])
    values this step0idx
  21. names ← ['al']

    15    idx = label_to_idx[k]16    names.append(records[idx]['name'])17print('RESULT:', names)
    values this step[] ['al']names
  22. k ← 'r'

    13names = []14for k in keys:15    idx = label_to_idx[k]
    values this step'p' 'r'k
  23. idx ← 2

    14for k in keys:15    idx = label_to_idx[k]16    names.append(records[idx]['name'])
    values this step0 2idx
  24. names ← ['al', 'cy']

    15    idx = label_to_idx[k]16    names.append(records[idx]['name'])17print('RESULT:', names)
    values this step['al'] ['al', 'cy']names
  25. for k in keys:

    13names = []14for k in keys:15    idx = label_to_idx[k]
  26. stdout ← RESULT: ['al', 'cy']

    16    names.append(records[idx]['name'])17print('RESULT:', names)
    values this stepRESULT: ['al', 'cy']stdout

With pandas

pd.DataFrame(records, index=labels) assigns string labels as the row index. df.loc[['p', 'r']] selects those rows by label and returns a sub-DataFrame with the matching index.

library.py
import pandas as pd
from dalib.display import set_display
set_display()

labels = ['p', 'q', 'r', 's']
records = [
    {'name': 'al', 'age': 20},
    {'name': 'bo', 'age': 25},
    {'name': 'cy', 'age': 22},
    {'name': 'di', 'age': 28},
]
df = pd.DataFrame(records, index=labels)
selected = df.loc[['p', 'r']]
print('index:', selected.index.tolist())
print('names:', selected['name'].tolist())
print('shape:', selected.shape)
print('RESULT:', selected['name'].tolist())
index: ['p', 'r']
names: ['al', 'cy']
shape: (2, 2)
RESULT: ['al', 'cy']

Implementation notes

  • loc is label-based: it looks up rows by index value, not by integer position. If the index is ['p', 'q', 'r', 's'], then df.loc['r'] returns the row labelled 'r' regardless of its physical position.
  • Label slices with loc are end-inclusive: df.loc['p':'r'] returns rows p, q, and r. This differs from iloc slices, which are end-exclusive.
  • Passing a list (loc[['p', 'r']]) selects specific labels in the given order; the result index matches the requested order, not the original order.
  • loc also accepts column labels as a second argument: df.loc[['p', 'r'], 'name'] returns just the name column for those rows as a Series.
  • Contrast with iloc (see select-rows-iloc): use iloc for position-based selection, loc for label-based selection.