2014-01-30 06:51:52 -08:00
|
|
|
^title Maps
|
2014-04-14 21:23:46 -07:00
|
|
|
^category types
|
2014-01-30 06:51:52 -08:00
|
|
|
|
2015-01-25 11:08:13 -08:00
|
|
|
A map is an *associative* collection. It holds a set of entries, each of which
|
|
|
|
|
maps a *key* to a *value*. The same data structure has a variety of names in
|
|
|
|
|
other languages: hash table, dictionary, association, table, etc.
|
|
|
|
|
|
|
|
|
|
You can create a map by placing a series of comma-separated entries inside
|
|
|
|
|
curly braces. Each entry is a key and a value separated by a colon:
|
|
|
|
|
|
|
|
|
|
:::dart
|
|
|
|
|
{
|
2015-01-25 21:39:22 -08:00
|
|
|
"George": "Harrison",
|
|
|
|
|
"John": "Lennon",
|
|
|
|
|
"Paul": "McCartney",
|
|
|
|
|
"Ringo": "Starr"
|
2015-01-25 11:08:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
This creates a map that maps the first names of the Beatles to their last
|
2015-05-03 11:10:31 -07:00
|
|
|
names. Syntactically, in a map literal, keys can be any literal, a variable
|
|
|
|
|
name, or a parenthesized expression. Values can be any expression. Here, we're
|
|
|
|
|
using string literals for both keys and values.
|
2015-01-25 11:08:13 -08:00
|
|
|
|
2015-01-25 21:39:22 -08:00
|
|
|
*Semantically*, values can be any object, and multiple keys may map to the
|
|
|
|
|
same value. Keys have a few limitations. They must be one of the immutable
|
|
|
|
|
built-in [value types](values.html) in Wren. That means a number, string,
|
|
|
|
|
range, bool, or `null`. You can also use a [class object](classes.html) as a
|
|
|
|
|
key.
|
2015-01-25 11:08:13 -08:00
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
In addition, even though they aren't strictly immutable, [fibers](fibers.html)
|
|
|
|
|
can be used as map keys. This is handy for storing data that's roughly
|
|
|
|
|
"thread-local" by using the current fiber as a map key.
|
|
|
|
|
|
|
|
|
|
The reason for this limitation—and the reason maps are called "*hash*
|
|
|
|
|
tables" in other languages—is that each key is used to generate a numeric
|
|
|
|
|
*hash code*. This lets a map locate the value associated with a key in constant
|
|
|
|
|
time, even in very large maps. Since Wren only knows how to hash certain
|
|
|
|
|
built-in types, only those can be used as keys.
|
2015-01-25 11:08:13 -08:00
|
|
|
|
|
|
|
|
## Adding entries
|
|
|
|
|
|
2015-01-25 21:39:22 -08:00
|
|
|
You add new key-value pairs to the map by using the [subscript operator][]:
|
|
|
|
|
|
|
|
|
|
:::dart
|
|
|
|
|
var capitals = {}
|
|
|
|
|
capitals["Georgia"] = "Atlanta"
|
|
|
|
|
capitals["Idaho"] = "Boise"
|
|
|
|
|
capitals["Maine"] = "Augusta"
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
If the key isn't already present, this adds it and associates it with the given
|
|
|
|
|
value. If the key is already there, this just replaces its value.
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
[subscript operator]: expressions.html#subscript-operators
|
2015-01-25 11:08:13 -08:00
|
|
|
|
|
|
|
|
## Looking up values
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
To find the value associated with some key, again you use your friend the
|
|
|
|
|
subscript operator:
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
:::dart
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(capitals["Idaho"]) // "Boise".
|
2015-01-25 21:39:22 -08:00
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
If the key is present, this returns its value. Otherwise, it returns `null`. Of
|
|
|
|
|
course, `null` itself can also be used as a value, so seeing `null` here
|
|
|
|
|
doesn't necessarily mean the key wasn't found.
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
To tell definitively if a key exists, you can call `containsKey()`:
|
|
|
|
|
|
|
|
|
|
:::dart
|
|
|
|
|
var belief = {"nihilism": null}
|
|
|
|
|
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(belief["nihilism"]) // "null" though key exists.
|
|
|
|
|
System.print(belief["solipsism"]) // Also "null".
|
|
|
|
|
System.print(belief.containsKey("nihilism")) // "true".
|
|
|
|
|
System.print(belief.containsKey("solipsism")) // "false".
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
You can see how many entries a map contains using `count`:
|
|
|
|
|
|
|
|
|
|
:::dart
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(capitals.count) // "3".
|
2015-01-25 11:08:13 -08:00
|
|
|
|
|
|
|
|
## Removing entries
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
To remove an entry from a map, call `remove()` and pass in the key for the
|
|
|
|
|
entry you want to delete:
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
:::dart
|
|
|
|
|
capitals.remove("Maine")
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(capitals.containsKey("Maine")) // "false".
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
If the key was found, this returns the value that was associated with it:
|
|
|
|
|
|
|
|
|
|
:::dart
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(capitals.remove("Georgia")) // "Atlanta".
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
If the key wasn't in the map to begin with, `remove()` just returns `null`.
|
|
|
|
|
|
|
|
|
|
If you want to remove *everything* from the map, just like with [lists][], you
|
2015-02-26 23:08:36 -08:00
|
|
|
can just call `clear()`:
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
:::dart
|
2015-02-26 23:08:36 -08:00
|
|
|
capitals.clear()
|
2015-09-15 07:46:09 -07:00
|
|
|
System.print(capitals.count) // "0".
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
[lists]: lists.html
|
2015-01-25 11:08:13 -08:00
|
|
|
|
|
|
|
|
## Iterating over the contents
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
The subscript operator works well for finding values when you know the key
|
|
|
|
|
you're looking for, but sometimes you want to see everything that's in the map.
|
|
|
|
|
For that, map exposes two methods: `keys` and `values`.
|
2015-01-25 21:39:22 -08:00
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
The first returns a [Sequence][] that [iterates][] over all of the keys in the
|
|
|
|
|
map, and the second returns one that iterates over the values.
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
[sequence]: core/sequence.html
|
|
|
|
|
[iterates]: control-flow.html#the-iterator-protocol
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
If you want to see all of the key-value pairs in a map, the easiest way is to
|
|
|
|
|
iterate over the keys and use each to look up its value:
|
2015-01-25 21:39:22 -08:00
|
|
|
|
|
|
|
|
:::dart
|
2015-09-15 07:46:09 -07:00
|
|
|
var birds = {
|
2015-01-25 21:39:22 -08:00
|
|
|
"Arizona": "Cactus wren",
|
|
|
|
|
"Hawaii": "Nēnē",
|
|
|
|
|
"Ohio": "Northern Cardinal"
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-15 07:46:09 -07:00
|
|
|
for (state in birds.keys) {
|
|
|
|
|
System.print("The state bird of " + state + " is " + birds[state])
|
2015-01-25 21:39:22 -08:00
|
|
|
}
|
|
|
|
|
|
2015-05-03 11:10:31 -07:00
|
|
|
This program will print the three states and their birds. However, the *order*
|
|
|
|
|
that they are printed isn't defined. Wren makes no promises about what order
|
|
|
|
|
keys and values will be iterated in when you use these methods. All it promises
|
|
|
|
|
is that every entry will appear exactly once.
|