3.15 Dictionaries
A dictionary is an instance of a datatype that maps keys to values. The following datatypes are all dictionaries:
vectors (using only exact integers as keys);
lists of pairs (an association list using equal? to compare keys); and
structures whose types have the prop:dict property.
A dictionary can be used as a two-valued sequence (see Sequences). The associations of the dictionary serve as elements of the sequence. See also in-dict, in-dict-keys, and in-dict-values.
Beware that dict? is not a constant-time test on pairs, since checking that v is an association list may require traversing the list.
Examples: |
> (dict? #hash((a . "apple"))) |
#t |
> (dict? '#("apple" "banana")) |
#t |
> (dict? '("apple" "banana")) |
#f |
> (dict? '((a . "apple") (b . "banana"))) |
#t |
(dict-mutable? d) → boolean? |
d : dict? |
Examples: |
> (dict-mutable? #hash((a . "apple"))) |
#f |
> (dict-mutable? (make-hash)) |
#t |
> (dict-mutable? '#("apple" "banana")) |
#f |
> (dict-mutable? (vector "apple" "banana")) |
#t |
> (dict-mutable? '((a . "apple") (b . "banana"))) |
#f |
(dict-can-remove-keys? d) → boolean? |
d : dict? |
Examples: |
> (dict-can-remove-keys? #hash((a . "apple"))) |
#t |
> (dict-can-remove-keys? '#("apple" "banana")) |
#f |
> (dict-can-remove-keys? '((a . "apple") (b . "banana"))) |
#t |
(dict-can-functional-set? d) → boolean? |
d : dict? |
Examples: |
> (dict-can-functional-set? #hash((a . "apple"))) |
#t |
> (dict-can-functional-set? (make-hash)) |
#f |
> (dict-can-functional-set? '#("apple" "banana")) |
#f |
> (dict-can-functional-set? '((a . "apple") (b . "banana"))) |
#t |
Examples: |
> (define h (make-hash)) |
> (dict-set! h 'a "apple") |
> h |
'#hash((a . "apple")) |
> (define v (vector #f #f #f)) |
> (dict-set! v 0 "apple") |
> v |
'#("apple" #f #f) |
(dict-set*! dict key v ... ...) → void? |
dict : (and/c dict? (not/c immutable?)) |
key : any/c |
v : any/c |
Examples: |
> (define h (make-hash)) |
> (dict-set*! h 'a "apple" 'b "banana") |
> h |
'#hash((b . "banana") (a . "apple")) |
> (define v1 (vector #f #f #f)) |
> (dict-set*! v1 0 "apple" 1 "banana") |
> v1 |
'#("apple" "banana" #f) |
> (define v2 (vector #f #f #f)) |
> (dict-set*! v2 0 "apple" 0 "banana") |
> v2 |
'#("banana" #f #f) |
(dict-set dict key v) → (and/c dict? immutable?) |
dict : (and/c dict? immutable?) |
key : any/c |
v : any/c |
Examples: |
> (dict-set #hash() 'a "apple") |
'#hash((a . "apple")) |
> (dict-set #hash((a . "apple") (b . "beer")) 'b "banana") |
'#hash((b . "banana") (a . "apple")) |
> (dict-set '() 'a "apple") |
'((a . "apple")) |
> (dict-set '((a . "apple") (b . "beer")) 'b "banana") |
'((a . "apple") (b . "banana")) |
(dict-set* dict key v ... ...) → (and/c dict? immutable?) |
dict : (and/c dict? immutable?) |
key : any/c |
v : any/c |
Examples: |
> (dict-set* #hash() 'a "apple" 'b "beer") |
'#hash((b . "beer") (a . "apple")) |
> (dict-set* #hash((a . "apple") (b . "beer")) 'b "banana" 'a "anchor") |
'#hash((b . "banana") (a . "anchor")) |
> (dict-set* '() 'a "apple" 'b "beer") |
'((a . "apple") (b . "beer")) |
> (dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'a "anchor") |
'((a . "anchor") (b . "banana")) |
> (dict-set* '((a . "apple") (b . "beer")) 'b "banana" 'b "balistic") |
'((a . "apple") (b . "balistic")) |
(dict-has-key? dict key) → boolean? |
dict : dict? |
key : any/c |
Examples: |
> (dict-has-key? #hash((a . "apple") (b . "beer")) 'a) |
#t |
> (dict-has-key? #hash((a . "apple") (b . "beer")) 'c) |
#f |
> (dict-has-key? '((a . "apple") (b . "banana")) 'b) |
#t |
> (dict-has-key? #("apple" "banana") 1) |
#t |
> (dict-has-key? #("apple" "banana") 3) |
#f |
> (dict-has-key? #("apple" "banana") -3) |
#f |
(dict-ref dict key [failure-result]) → any | ||||||||||||
dict : dict? | ||||||||||||
key : any/c | ||||||||||||
|
If failure-result is a procedure, it is called (through a tail call) with no arguments to produce the result.
Otherwise, failure-result is returned as the result.
Examples: |
> (dict-ref #hash((a . "apple") (b . "beer")) 'a) |
"apple" |
> (dict-ref #hash((a . "apple") (b . "beer")) 'c) |
hash-ref: no value found for key: 'c |
> (dict-ref #hash((a . "apple") (b . "beer")) 'c #f) |
#f |
> (dict-ref '((a . "apple") (b . "banana")) 'b) |
"banana" |
> (dict-ref #("apple" "banana") 1) |
"banana" |
> (dict-ref #("apple" "banana") 3 #f) |
#f |
> (dict-ref #("apple" "banana") -3 #f) |
contract violation: expected <exact-nonnegative-integer?>, |
given: -3 |
contract on dict-ref from |
(file |
/var/tmp/racket/collects/racket/dict.rkt) |
blaming top-level |
contract: |
(->i |
((d dict?) (k (d) ...)) |
((default any/c)) |
any) |
at: <collects>/racket/dict.rkt:147.2 |
Examples: |
> (dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'a) |
procedure dict-ref!: expects 3 arguments, given 2: |
'#hasheq((a . "apple") (b . "beer")) 'a |
> (dict-ref! (make-hasheq '((a . "apple") (b . "beer"))) 'c 'cabbage) |
'cabbage |
> (define h (make-hasheq '((a . "apple") (b . "beer")))) |
> (dict-ref h 'c) |
hash-ref: no value found for key: 'c |
> (dict-ref! h 'c (λ () 'cabbage)) |
'cabbage |
> (dict-ref h 'c) |
'cabbage |
| ||||||||||||||||||||||||||||
dict : (and/c dict? (not/c immutable?)) | ||||||||||||||||||||||||||||
key : any/c | ||||||||||||||||||||||||||||
updater : (any/c . -> . any/c) | ||||||||||||||||||||||||||||
|
Examples: |
> (define h (make-hash)) |
> (dict-update! h 'a add1) |
hash-ref: no value found for key: 'a |
> (dict-update! h 'a add1 0) |
> h |
'#hash((a . 1)) |
> (define v (vector #f #f #f)) |
> (dict-update! v 0 not) |
> v |
'#(#t #f #f) |
(dict-update dict key updater [failure-result]) | ||||||||||||
→ (and/c dict? immutable?) | ||||||||||||
dict : dict? | ||||||||||||
key : any/c | ||||||||||||
updater : (any/c . -> . any/c) | ||||||||||||
|
Examples: |
> (dict-update #hash() 'a add1) |
hash-ref: no value found for key: 'a |
> (dict-update #hash() 'a add1 0) |
'#hash((a . 1)) |
> (dict-update #hash((a . "apple") (b . "beer")) 'b string-length) |
'#hash((b . 4) (a . "apple")) |
(dict-remove! dict key) → void? |
dict : (and/c dict? (not/c immutable?)) |
key : any/c |
Examples: |
> (define h (make-hash)) |
> (dict-set! h 'a "apple") |
> h |
'#hash((a . "apple")) |
> (dict-remove! h 'a) |
> h |
'#hash() |
(dict-remove dict key) → (and/c dict? immutable?) |
dict : (and/c dict? immutable?) |
key : any/c |
Examples: |
> (define h #hash()) |
> (define h (dict-set h 'a "apple")) |
> h |
'#hash((a . "apple")) |
> (dict-remove h 'a) |
'#hash() |
> h |
'#hash((a . "apple")) |
> (dict-remove h 'z) |
'#hash((a . "apple")) |
> (dict-remove '((a . "apple") (b . "banana")) 'a) |
'((b . "banana")) |
Example: |
> (dict-map #hash((a . "apple") (b . "banana")) vector) |
'(#(b "banana") #(a "apple")) |
Example: | |||
| |||
|
(dict-count dict) → exact-nonnegative-integer? |
dict : dict? |
Examples: |
> (dict-count #hash((a . "apple") (b . "banana"))) |
2 |
> (dict-count #("apple" "banana")) |
2 |
(dict-iterate-first dict) → any/c |
dict : dict? |
Examples: |
> (dict-iterate-first #hash((a . "apple") (b . "banana"))) |
0 |
> (dict-iterate-first #hash()) |
#f |
> (dict-iterate-first #("apple" "banana")) |
0 |
> (dict-iterate-first '((a . "apple") (b . "banana"))) |
#<assoc-iter> |
(dict-iterate-next dict pos) → any/c |
dict : dict? |
pos : any/c |
Examples: |
> (define h #hash((a . "apple") (b . "banana"))) |
> (define i (dict-iterate-first h)) |
> i |
0 |
> (dict-iterate-next h i) |
1 |
> (dict-iterate-next h (dict-iterate-next h i)) |
#f |
(dict-iterate-key dict pos) → any |
dict : dict? |
pos : any/c |
Examples: |
> (define h '((a . "apple") (b . "banana"))) |
> (define i (dict-iterate-first h)) |
> (dict-iterate-key h i) |
'a |
> (dict-iterate-key h (dict-iterate-next h i)) |
'b |
(dict-iterate-value dict pos) → any |
dict : dict? |
pos : any/c |
Examples: |
> (define h '((a . "apple") (b . "banana"))) |
> (define i (dict-iterate-first h)) |
> (dict-iterate-value h i) |
"apple" |
> (dict-iterate-value h (dict-iterate-next h i)) |
"banana" |
Examples: | ||
> (define h #hash((a . "apple") (b . "banana"))) | ||
| ||
'("b = \"banana\"" "a = \"apple\"") |
(in-dict-keys dict) → sequence? |
dict : dict? |
Examples: | ||
> (define h #hash((a . "apple") (b . "banana"))) | ||
| ||
'(b a) |
(in-dict-values dict) → sequence? |
dict : dict? |
Examples: | ||
> (define h #hash((a . "apple") (b . "banana"))) | ||
| ||
'("banana" "apple") |
(in-dict-pairs dict) → sequence? |
dict : dict? |
Examples: | ||
> (define h #hash((a . "apple") (b . "banana"))) | ||
| ||
'((b . "banana") (a . "apple")) |
Examples: |
> (define h #hash((a . "apple") (b . "banana"))) |
> (dict-keys h) |
'(b a) |
(dict-values dict) → list? |
dict : dict? |
Examples: |
> (define h #hash((a . "apple") (b . "banana"))) |
> (dict-values h) |
'("banana" "apple") |
(dict->list dict) → list? |
dict : dict? |
Examples: |
> (define h #hash((a . "apple") (b . "banana"))) |
> (dict->list h) |
'((b . "banana") (a . "apple")) |
ref : a procedure like dict-ref that accepts either two or three arguments
set! : a procedure like dict-set! that accepts three arguments, or #f if mutation is not supported
set : a procedure like dict-set that accepts three arguments and returns an updated dictionary, or #f if functional update is not supported
remove! : a procedure like dict-remove! that accepts two arguments, or #f if mutation is not supported or if key removal is not supported
remove : a procedure like dict-remove that accepts two arguments and returns an updated dictionary, or #f if functional update or key removal is not supported
count : a procedure like dict-count that accepts one argument
iterate-first : a procedure like dict-iterate-first that accepts one argument
iterate-next : a procedure like dict-iterate-next that accepts two arguments; the procedure is responsible for checking that the second argument is a valid position for the first argument
iterate-key : a procedure like dict-iterate-key that accepts two arguments; the procedure is responsible for checking that the second argument is a valid position for the first argument
iterate-value : a procedure like dict-iterate-value that accepts two arguments; the procedure is responsible for checking that the second argument is a valid position for the first argument
(list dict-vector |
(vector type-key-contract |
type-value-contract |
type-iter-contract |
instance-key-contract |
instance-value-contract |
instance-iter-contract)) |
The first vector must be suitable as a value for prop:dict (in addition, it must be an immutable vector). The second vector must contain six elements; each of the first three is a contract for the dictionary type’s keys, values, and positions, respectively. Each of the second three is either #f or a procedure used to extract the contract from a dictionary instance.
| ||
| ||
|
| |||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||
|
The make-custom-hash and make-weak-custom-hash functions create a mutable dictionary that does not support functional update, while make-immutable-custom-hash creates an immutable dictionary that supports functional update. The dictionary created by make-weak-custom-hash retains its keys weakly, like the result of make-weak-hash.
Dictionaries created by make-custom-hash and company are equal? when they have the same mutability and key strength, the associated procedures are equal?, and the key–value mappings are the same when keys and values are compared with equal?.
Examples: | ||||||
| ||||||
> (dict-set! h 1 'one) | ||||||
> (dict-ref h "1") | ||||||
'one |