Skip to content
The AI Agent Factory

13.6 Lists and dictionaries

Approved by
Panaversity ·
12 min read

In everyday life. A grocery list is in order: first milk, then bread. A coat check finds your coat by its ticket number, and a ticket they never gave out gets you nothing.

What you will learn. Two questions for every sort and lookup: what does it compare, and what if the name is missing?

Why it matters. A count and a total cannot see a wrong order or a missing name.

List or dictionary?

A list holds items in order, like the grocery list, and you find each one by its position. A dictionary is the coat check. It holds values under names, called keys, as the coat check holds coats under ticket numbers. One looks like { V005: "Hocking Valley Pallets" }. TypeScript uses an object, written with braces, and Python a dict.

In 13.4, each invoice was a list, and you had to remember that position 1 was the status. A record gives each value a name instead. It is a dictionary that holds one thing, such as one invoice. So inv[1] becomes inv.status in TypeScript and inv["status"] in Python.

Figure 13.7. The INV-8301 row of invoices.csv becoming a record. The header names become keys, the cells become values, and the amount "482500" is converted from text to the whole number 482500. Blank or invalid amounts are rejected.

Figure 13.7. A row becomes a record. The header gives the keys. Every value starts as text until the code converts it.

What does a sort compare, and why can't my count and total see it?

It compares what its rule says. To sort a stack of invoices by hand, you take two at a time and decide which goes first, until the whole stack is in order. A sort does the same, and its rule is that one decision. With no rule, it uses a default, and the two languages differ. So read every sort line an agent writes.

At work. Ana's check from Chapter 12 says Friday has 8 invoices, $19,229.53. The controller asks for Friday's list, largest first. The agent sorts it, the tests pass, and its summary matches her check. Before the agent runs the list, she reads the one line that changed.

// take two invoices, a and b: the larger amount goes first
friday.sort((a, b) => b.cents - a.cents);

friday is the list of Friday's invoices. The line is the hand sort's one decision: which of two invoices goes first. Each language writes that decision its own way.

LanguageHow to read the rule
TypeScript(a, b) => b.cents - a.cents takes two invoices, a and b, and subtracts their amounts. A positive answer puts b first and a negative answer puts a first, so the larger amount comes first.
Pythonlambda makes a small function with no name. lambda inv: inv["cents"] says "compare each invoice by its cents", and reverse=True puts the largest first.

She writes in NOTES.md: "It compares the amounts as numbers, largest first." So she predicts INV-8305, at 735000 cents, first, and INV-8312, at 19995 cents, last.

The run prints those two first and last. But a count and a total come out the same in any order, so her check cannot see this line. So she lists amounts of different lengths in the order they must come out, and has the agent turn her list into a test. It passes, and it will fail if a later change breaks the order.

What does a sort do when it has no rule?

It uses a default, and here the two languages differ. TypeScript's cents.sort() compares numbers as text, one character at a time, as if putting words in alphabetical order. So 482500 comes before 61875, because 4 comes before 6. Python's sorted compares numbers as numbers, unless key=str tells it to compare them as text. Amounts of different lengths are where this shows. Predict both lines.

const cents = [735000, 482500, 61875];
console.log(cents.sort());                  // no rule
console.log(cents.sort((a, b) => a - b));   // rule: the smaller number first
[ 482500, 61875, 735000 ]
[ 61875, 482500, 735000 ]

What happens to a missing key?

Think of a ticket the coat check never gave out. TypeScript hands you nothing, undefined, and keeps running. Python stops with a KeyError. A key must match exactly, capital letters too, so v005 is not V005. A position past the end of a list is missing in the same way: undefined in TypeScript, an IndexError in Python.

At work. Brightline's export names each vendor by id, such as V005. To print names, the script builds a dictionary from vendors.csv and looks up each invoice's vendor id. Ana asks: what happens when an invoice names an id that is not in the dictionary?

names is a dictionary of many vendors, with each name kept under its id. Python also has a careful way to ask: .get() gives None for a missing key, or a default you pass it, as in .get(key, 0). Predict each line.

// names: a dictionary whose keys and values are text
const names: Record<string, string> = { V001: "Midwest Packaging Co.", V005: "Hocking Valley Pallets" };
console.log(names["V005"]);   // a ticket it gave out
console.log(names["V099"]);   // a ticket it never gave out
Hocking Valley Pallets
undefined

Try it

The file in 13-6 holds a lookup and a sort. Run it and investigate, as in 13.1. Watch the missing vendor, V099.

Modify. Send: "Please change the sort in the file to put the largest amount first. Don't run it yet." The amounts are 735000, 482500 and 61875. Say which will come first. Then ask the agent to run it.

Make. Send: "Please make a new file in 13-6 called mine that keeps each vendor's terms under its id, looks up one vendor that exists and one that doesn't, and prints both. Don't run it yet." Say what the missing one will print, and then ask the agent to run it.

What you should see. 735000 comes first after your change. In mine, the missing vendor gives undefined in TypeScript. In Python, it depends on how the agent looked it up, so read that line.

The operating rule: for every lookup, ask what happens when the key is missing. For every sort, ask what it compares.

Next. Those values arrive from files, as text and dates. 13.7 shows their hidden rules.

Check yourself

Question 1 / 7

0 answered

The vendor id comes from a file that someone typed by hand.const terms: Record<string, string> = { V031: "Net 30", V032: "Net 15" } const fromFile = "v031" console.log(terms[fromFile])What does it print?

Owner
Panaversity