docs/src/reference-main-maps.md
Miller data types are listed on the Data types page; here we focus specifically on maps.
On the whole, maps are as in most other programming languages. However, following the Principle of Least Surprise and aiming to reduce keystroking for Miller's most-used streaming-record-processing model, there are a few differences as noted below.
Map literals are written in curly braces with string keys any Miller data type (including other maps, or arrays) as values. Also, integers may be given as keys although they'll be stored as strings.
<pre class="pre-highlight-in-pair"> <b>mlr -n put '</b> <b> end {</b> <b> x = {"a": 1, "b": {"x": 2, "y": [3,4,5]}, 99: true};</b> <b> dump x;</b> <b> print x[99];</b> <b> print x["99"];</b> <b> }</b> <b>'</b> </pre> <pre class="pre-non-highlight-in-pair"> { "a": 1, "b": { "x": 2, "y": [3, 4, 5] }, "99": true } true true </pre>As with arrays and argument-lists, trailing commas are supported:
<pre class="pre-highlight-in-pair"> <b>mlr -n put '</b> <b> end {</b> <b> x = {</b> <b> "a" : 1,</b> <b> "b" : 2,</b> <b> "c" : 3,</b> <b> };</b> <b> print x;</b> <b> }</b> <b>'</b> </pre> <pre class="pre-non-highlight-in-pair"> { "a": 1, "b": 2, "c": 3 } </pre>The current record, accessible using $*, is a map.
The collection of all out-of-stream variables, @*, is a map.
Also note that several built-in functions operate on maps and/or return maps.
Miller maps preserve insertion order. So if you write @m["y"]=7 and then @m["x"]=3 then any loop over
the map @m will give you the kays "y" and "x" in that order.
All Miller map keys are strings. If a map is indexed with an integer for either
read or write (i.e. on either the right-hand side or left-hand side of an
assignment) then the integer will be converted to/from string, respectively. So
@m[3] is the same as @m["3"]. The reason for this is for situations like
operating on all records where it's important to
let people do @records[NR] = $*.
Indexing any as-yet-assigned local variable or out-of-stream variable results in auto-create of that variable as a map variable:
<pre class="pre-highlight-in-pair"> <b>mlr --csv --from example.csv put -q '</b> <b> # You can do this but you do not need to:</b> <b> # begin { @last_rates = {} }</b> <b> @last_rates[$shape] = $rate;</b> <b> end {</b> <b> dump @last_rates;</b> <b> }</b> <b>'</b> </pre> <pre class="pre-non-highlight-in-pair"> { "triangle": 5.8240, "square": 8.2430, "circle": 8.3350 } </pre>This also means that auto-create results in maps, not arrays, even if keys are integers.
If you want to auto-extend an array, initialize it explicitly to [].
Similarly, maps are auto-deepened: you can put @m["a"]["b"]["c"]=3
without first setting @m["a"]={} and @m["a"]["b"]={}. The reason for this
is for doing data aggregations: for example if you want compute keyed sums, you
can do that with a minimum of keystrokes.
See single-variable for-loops and key-value for-loops.
See the flatten/unflatten page.