Reported September 2026
Stripehash table

Project and Filter Structured Records

Reported by candidates from Stripe's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Stripe OA. Under 2s to a working solution.
Founder's read

Stripe reported this one in September 2026, and it looks friendlier than it is. Strip the wording and it's a lookup table plus a loop. Map field names to column indexes once, validate everything up front, then scan records and project the columns you need. If you've got an OA invite for Stripe, expect the grind to be edge cases, not cleverness. The INVALID rule, empty filters, and zero matches each trip people up. If you blank mid-assessment, StealthCoder runs invisibly on your desktop and gives you a working solution as a safety net.

The problem

You are given a shared schema fieldNames and a collection of records. Each record is an array of string values aligned with the schema, so records[i][j] is the value of field fieldNames[j].
A projection request lists selectedFields. Each row of filters contains exactly two strings: a field name and its expected value. A record matches only when all filter conditions equal the corresponding record values using case-sensitive string equality.
First validate every name in selectedFields and every filter field name. If any name is absent from fieldNames, return exactly [["INVALID"]]. Otherwise, return one projected row for every matching record. Preserve record order, and place each row's values in selectedFields order. An empty filter list matches every record, while a valid request with no matching records returns an empty array.

Function
projectAndFilterRecords(fieldNames: String[], records: String[][], selectedFields: String[], filters: String[][]) → String[][]

Examples
Example 1
fieldNames = ["name","email","country","tier"]
records = [["Ada","ada@example.com","US","pro"],["Ben","ben@example.com","CA","pro"],["Cy","cy@example.com","US","basic"]]
selectedFields = ["name","email"]
filters = [["country","US"],["tier","pro"]]
return = [["Ada","ada@example.com"]]
Only Ada has both country = US and tier = pro. The returned row follows the requested name, then email, order.
Example 2
fieldNames = ["name","team"]
records = [["Ana","risk"],["Bo","core"]]
selectedFields = ["team","name"]
filters = []
return = [["risk","Ana"],["core","Bo"]]
With no filters, both records match. Input row order is preserved, and each row is projected into team, then name, order.
Example 3
fieldNames = ["name","team"]
records = [["Ana","risk"]]
selectedFields = ["name"]
filters = [["country","US"]]
return = [["INVALID"]]
The schema has no country field, so the whole request is invalid before any records are filtered.

Constraints
1 <= fieldNames.length <= 100.
Every field name is a non-empty printable ASCII string of length at most 32, and fieldNames contains no duplicates.
0 <= records.length <= 100000, and every record has exactly fieldNames.length values.
1 <= selectedFields.length <= 100; its entries are distinct non-empty printable ASCII field names.
0 <= filters.length <= 100, and every filter has exactly two strings: a non-empty printable ASCII field name and an expected value.
Each record value and expected value has at most 100 printable ASCII characters.
The total number of values across all records is at most 200000.
Field-name and value comparisons are case-sensitive.

Reported by candidates. Source: FastPrep

Pattern and pitfall

The trick is to build a hash map from field name to index once, so every lookup is O(1) instead of scanning fieldNames per record. Validate first: check every selectedFields name and every filter field name against the map. If any is missing, return [["INVALID"]] immediately, before touching records. Then convert filters into (index, expectedValue) pairs and selectedFields into an index list. For each record, check all filter pairs with exact string equality, and if they pass, build the row by pulling values in selectedFields order. Common pitfalls: validating lazily inside the record loop, which breaks when records is empty. Returning [["INVALID"]] versus an empty array also gets confused. Remember that no filters means everything matches. Complexity is O(total values + records * (filters + selected)). If you freeze during the live OA, StealthCoder is the hedge that reads the problem and hands you this structure.

StealthCoder is the hedge for the one pattern you didn't drill. It runs invisibly during the screen share.

If this hits your live OA

You can drill Project and Filter Structured Records cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. If you're reading this with an OA window open, you're who this was built for.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Stripe's OA.

Stripe reuses patterns across OAs. If you're reading this with an OA window open, you're who this was built for. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Project and Filter Structured Records FAQ

How hard is the Stripe Project and Filter Structured Records problem really?+

Easy on algorithm, medium on care. There's no clever data structure beyond a hash map from field name to index. Points get lost on validation order, the exact INVALID return shape, and preserving selectedFields order rather than schema order.

What's the trick to solving it fast?+

Precompute a name-to-index map, validate all names before looping, then convert filters and selections into index arrays. Inside the loop you only do integer indexing and string equality. That keeps it linear in the total number of values.

What edge cases should I test before submitting?+

Test an empty filters list, which matches all records. Test zero records with valid names, which returns an empty array. Test an invalid name in filters only, and one in selectedFields only. Also check case sensitivity, like US versus us, which must not match.

Is INVALID different from an empty result?+

Yes. An unknown field name anywhere in selectedFields or filters returns exactly [["INVALID"]]. A valid request where nothing matches returns an empty array. Checking validity before iterating records keeps those two cases from blurring together.

How do I prepare for this in 48 hours?+

Practice writing the index-map plus filter-and-project loop from scratch until it takes a few minutes. Then rehearse the edge cases above. Pay attention to the output shape and to reading constraints, since 100000 records means you can't do per-record name searches.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Stripe.

OA at Stripe?
Invisible during screen share
Get it