Filtering with select and map

jq · Essentials · 10 min

Filtering a list down to what you care about, like failed jobs or large files, is the core of most jq one-liners.

select(cond) outputs its input if the condition is true, and nothing otherwise. Used after .[], it filters a stream:

.[] | select(.status == "failed")

Conditions use ==, !=, <, <=, >, >=, combined with and, or and not (which is a filter, written cond | not). In jq only false and null are falsy; 0, "" and [] count as true.

map(f) applies f to every element of an array and returns a new array. It is exactly [.[] | f]. So these two are equivalent ways to filter an array while keeping it an array:

  • map(select(.price > 100))
  • [.[] | select(.price > 100)]

Useful tests inside select: has("key"), .tags | index("urgent"), .name | startswith("tmp"), test("regex"), and IN(...) for membership: select(.env | IN("prod","staging")).

map_values(f) does the same for an object's values. Note that select drops non-matching inputs entirely, so map(select(...)) can shorten an array, while map(if ... then ... else . end) keeps its length.

Example

cat > jobs.json <<'EOF'
[{"id":1,"status":"ok","ms":120},{"id":2,"status":"failed","ms":900},
 {"id":3,"status":"failed","ms":40},{"id":4,"status":"ok","ms":3000}]
EOF
jq -c '.[] | select(.status == "failed") | .id' jobs.json   # 2  3
jq -c 'map(select(.ms > 500) | .id)' jobs.json              # [2,4]
jq -c 'map(select(.status == "ok" and .ms < 1000))' jobs.json
# [{"id":1,"status":"ok","ms":120}]
jq -c 'map(.ms * 2)' jobs.json                              # [240,1800,80,6000]
jq -c '[.[] | select(.id | IN(1,4)) | .id]' jobs.json        # [1,4]
jq 'map(select(.status != "ok")) | length' jobs.json        # 2

Remember

  • select(cond) passes input through only when cond is true
  • map(f) = [.[] | f]; map(select(...)) filters an array
  • Only false and null are falsy in jq

Watch out for

  • Using select on an array directly (select(.x) on [...]) instead of on its elements; iterate or map first.

Check yourself

  1. Which filter returns an array of only the items whose price is above 10?
  2. What is `0 | if . then "yes" else "no" end`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: jqlang.org/manual/