-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exercism jq Cookbook #5055
Comments
|
This is awesome! I want to really revamp the docs repo, so this will be perfect there when that's done. |
|
This is awesome work! I've seen several people use |
|
I recently used this to map all the exercises with a given unlock to another unlock. jq 'setpath(["exercises"]; [] + .exercises |
map(if .unlocked_by == "atbash-cipher"
then setpath(["unlocked_by"]; "luhn")
else . end))' ./exercism-rust/config.json |
|
Hello 👋 With the launch of Exercism v3, we are closing all issues in this repository to help give us a clean slate to detect new problems. If this issue is still relevant to Exercism v3 (e.g. it's a feature that we haven't implemented in v3, or a bug that still exists), please reopen it and we will review it and post an update on it as soon as we get chance. Thanks for helping make Exercism better, and we hope you enjoy v3 🙂 |
For a while I've wanted to make a jq cookbook aimed at Exercism. So far this has only amounted to draft blog posts, so to get the ball rolling, I'm collecting practical snippets here. Please comment with corrections or improvements, additional snippets or questions of how to do something, and I will move them to the top.
For now, the "tutorial" part of the cookbook is just embedded as it goes along. I worked on a separate section, but since the scope wasn't clear, I kept going back and revising it constantly, and it became a drag. I'll extract this part eventually.
Eventually we may find a better place to keep this cookbook.
A list of all exercise slugs for a track
Explanation:
--compact-output/-c: Strip all whitespace.[ .exercises[].slug ]is equivalent to[ .exercises | .[] | .slug ]..exercises, is filtered through the array value iterator,.[], which splits each entry into multiple results, each of which is filtered through.slugthat reduces an object to the value indexed by the key"slug".[ .[] ]is the no-op filter for lists:.[]breaks the list apart, and[ ... ]assembles it again.[ ... ]constructor.--raw-output/-r: "With this option, if the filter's result is a string then it will be written directly to standard output rather than being formatted as a JSON string with quotes. This can be useful for making jq filters talk to non-JSON-based systems."-rversion doesn't pack the result into a list, so each of the multiple results is a string and gets printed without the JSON string wrapping.map()is a built-in higher-order combinator. If it didn't exist, it could be written as:A list of non-deprecated exercises for a track
Explanation:
select(.deprecated != true).select(): "The functionselect(foo)produces its input unchanged iffooreturns true for that input, and produces no output otherwise.".[]operator splits the list into multiple results, the subsequent filtersselect(.deprecated != true)and.slugtake each of those results as their implicit argument.map(f) | map(g)=[ .[] | f ] | [ .[] | g ]=[ .[] | (f | g) ]=map(f | g).notis a combinator, so it takes its argument implicitly.nullis interpreted asfalse.map(select(...))filters, but this is becauseselect()either outputs zero or one result based on its predicate, somap(f)is better understood as "concat ∘ map f".A list of core exercises for a track
It should be reasonable to assume that no exercises are marked as both core and deprecated, but I don't think this is documented anywhere, and
configlet lint .does not complain about it.A list of canonical exercises
Explanation:
(cd ... && ...)invokes a sub-shell within which the directory change happens only.cd ... && printf '%s\0' *is safer thanls ...becauselswill not differentiate between linebreaks between filenames and linebreaks in filenames.*is glob expansion.\0is picked as a separator because filenames cannot contain NUL bytes.--slurp/-s: "Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once."--raw-input/-R: "Don't parse the input as JSON. Instead, each line of text is passed to the filter as a string. If combined with--slurp, then the entire input is passed to the filter as a single long string."split("separator")works as you may expect."\u0000"is a NUL byte in a jq string.sub("\u0000$"; ""). Yes, that's regex.A list of canonical exercises not implemented for a track
$()(because bash can't actually store NUL bytes in strings), so a workaround is made.--raw-input/-R: "Don't parse the input as JSON. Instead, each line of text is passed to the filter as a string. If combined with--slurp, then the entire input is passed to the filter as a single long string."--argjson varname value: "This option passes a JSON-encoded value to the jq program as a predefined variable. If you run jq with--argjson foo 123, then$foois available in the program and has the value123.".exercises | map(.slug)is necessary because-binds tighter than|.A list of all used topics for a track
Explanation:
.exercises | map(.topics)is a list of lists of strings..exercises | map(.topics[])would work, but because.topicscan benullandnull[]is a run-time error, we remove thenulls withselect(. != null).unique.-rversion an[]array value iterator is added at the end to produce multiple string results instead of a single list result with strings in it.A map of (non-deprecated) exercise slugs to unlocking exercise slug
Explanation:
.exercises | ...reduces the config to the list of its exercises.map(select(.deprecated | not))filters out deprecated exercises.map(... | { (.slug): .unlocked_by })converts the remaining into a smaller object.... | addmerges all those objects into a single one with each slug key being unique.The text was updated successfully, but these errors were encountered: