How do I find the first item matching a condition in EK9?
← Common Collection Tasks · Ref: Q184
EK9 uses stream pipelines with filter and head 1 to find the first matching item.
FILTER + HEAD 1
The standard pattern for finding the first match:
results <- cat items | filter by predicate | head 1 | collect as List of Integer
Returns a list with 0 or 1 elements. Check if empty to determine whether a match was found.
CHECK RESULT
if ~results is empty found <- results.getOrDefault(0, defaultVal) stdout.println(`Found: ${found}`)
WHY HEAD 1
head 1 stops processing after the first match is found. This is EK9's equivalent of early exit: the stream terminates as soon as one element passes through.
See Q89 for stream pipelines. See Q125 for head/tail/skip. See Q162 for safe list access. See Q185 for any/all match.
Example
defines module qa.collectiontasks.findfirst defines function isEven() as pure -> num as Integer <- rtn as Boolean: num mod 2 == 0 isLong() as pure -> str as String <- rtn <- Boolean() expectedValue <- 4 rtn: length str > expectedValue defines program FindFirstMatchDemo() stdout <- Stdout() // === FILTER + HEAD 1 === numbers <- [1, 3, 5, 4, 6, 8] firstEven <- cat numbers | filter by isEven | head 1 | collect as List of Integer stdout.println(`First even: ${firstEven}`) // === CHECK IF FOUND === if ~firstEven is empty found <- firstEven.getOrDefault(0, 0) stdout.println(`Found: ${found}`) // === NO MATCH FOUND === allOdd <- [1, 3, 5, 7, 9] noMatch <- cat allOdd | filter by isEven | head 1 | collect as List of Integer stdout.println(`No match result: ${noMatch}`) if noMatch is empty stdout.println("No even number found") // === FIND FIRST IN STRINGS === names <- ["Bob", "Jo", "Alice", "Charlie"] longNames <- cat names | filter by isLong | head 1 | collect as List of String stdout.println(`First long name: ${longNames}`) // === ALL MATCHES (WITHOUT HEAD) === allEvens <- cat numbers | filter by isEven | collect as List of Integer stdout.println(`All evens: ${allEvens}`)
Common mistakes
E07520 — A predicate function used with 'filter by' must return Boolean. Returning String instead of Boolean triggers E07520 because the stream filter needs a true/false decision. See ek9 -h E07520 for details.
Incorrect:
<- rtn as String: $num
Correct:
<- rtn as Boolean: num mod 2 == 0
Other ways to ask this
- What is the EK9 equivalent of find() or findFirst()?
- How do I search a list for the first match in EK9?
- How do I filter a list and take the first result in EK9?
Coming from another language?
Java: list.stream().filter(pred).findFirst() returns Optional. Python: next((x for x in items if pred(x)), default). Rust: iter.find(pred) returns Option. Go: manual loop with break. JavaScript: arr.find(pred). Kotlin: list.find(pred), list.firstOrNull(pred). EK9: cat list | filter by pred | head 1 | collect as List, no break needed.
Keywords: find, search, first, stream, head, filter, predicate, match, task, condition, pipeline, collection