cswork / libraryOpen practice workspace

Coding questions · Karat

Join tables to map userId to name

This question evaluates a candidate's skills in relational data joining, data integration, and numeric reconciliation for mapping userId to customerName across multiple tables.

Problem

You are given three tables represented as 2D string arrays (each row is a record, no headers). You need to produce a mapping from userId → customerName by matching and joining information across tables.

Table 1: customers

Each row: [customerName, email, productName, quantity]

  • quantity is an integer in string form.
  • Assumption: each customer buys only one type of product (i.e., one productName per customer).

Table 2: orders

Each row: [userId, email, orderTotal]

  • orderTotal is a number in string form (integer or decimal).
  • email may be null (or an empty string, depending on how the input is represented).

Table 3: products

Each row: [productName, unitPrice]

  • unitPrice is a number in string form.

Matching / Join requirement

For each order record, identify which customer placed it, then output userId -> customerName.

Use these matching rules:

  1. If orders.email is present (non-null/non-empty), match the customer by email.
  2. If orders.email is missing, match by using the fact that:
    • orderTotal = quantity * unitPrice for the customer’s purchased product.
    • Use customers.productName joined to products.productName to get unitPrice.

Output

Return a mapping/dictionary from userId to customerName for all orders.

Assumptions / Edge cases

  • If multiple customers could match an order (e.g., same computed total), specify and implement a deterministic tie-breaker (e.g., pick lexicographically smallest name) or return all candidates—clarify with the interviewer.
  • Assume inputs are well-formed aside from possible null/empty emails.

Join Tables to Map userId to Customer Name

You are given three tables represented as 2D arrays of strings (each inner list is a row, with no headers). Your task is to build a mapping from each order's userId to the corresponding customerName by joining information across the tables.

Tables:

  1. customers: each row is [customerName, email, productName, quantity]

    • quantity is an integer represented as a string.
    • Each customer buys exactly one product type (one productName per customer).
  2. orders: each row is [userId, email, orderTotal]

    • orderTotal is a number represented as a string (may be integer or decimal).
    • email may be missing, represented as None or an empty string "".
  3. products: each row is [productName, unitPrice]

    • unitPrice is a number represented as a string.

Matching rules for each order:

  1. If orders.email is present (not None and not empty) and matches one or more customer emails, match by email.
  2. Otherwise, match by total price using: orderTotal = quantity * unitPrice, where unitPrice is looked up via customers.productName joined with products.productName.

Ambiguity / tie-breaker:

  • If multiple customers match by email or by computed total, return the lexicographically smallest customerName among the matches.

Return a dictionary mapping userId (string) to customerName (string) for all orders.

Constraints

  • 1 <= len(customers), len(orders), len(products) <= 100000
  • quantity is an integer string that fits in 32-bit signed range
  • unitPrice and orderTotal are valid numeric strings (integer or decimal)
  • orders.email may be None or ""
  • If multiple customers match, choose the lexicographically smallest customerName
  • Inputs are well-formed so that each order can be matched by email or by total

Examples

Example 1

Input: ([['Alice','a@x.com','Book','2'],['Bob','b@x.com','Pen','5']], [['u1','a@x.com','20'],['u2',None,'10']], [['Book','10'],['Pen','2']])
Output: {'u1': 'Alice', 'u2': 'Bob'}

Explanation: u1 matches by email -> Alice. u2 has no email, total 10 matches Bob because 5*2=10.

Example 2

Input: ([['Amy','amy@mail','Widget','1'],['Zoe','zoe@mail','Widget','1'],['Bob','bob@mail','Gadget','2']], [['1',None,'9.99'],['2','','9.99'],['3',None,'9.990'],['4','bob@mail','10']], [['Widget','9.99'],['Gadget','5']])
Output: {'1': 'Amy', '2': 'Amy', '3': 'Amy', '4': 'Bob'}

Explanation: Orders 1-3 match by total 9.99; both Amy and Zoe match, pick lexicographically smallest -> Amy. Order 4 matches by email -> Bob.