This module exposes the same API as Dict
.
Since JavaScript's number type is kind of messed up, Elm's Int
is not particularly
well-behaved wrt. bitwise operations. Currently, JS supports 32 bit integers, so there is
probably enough room for key picks. However, when sanitizing user input, it is mandatory
that a prior isValidKey
or one of the safe versions in IntDict.Safe
is used! This is
to prevent the overflow behavior.
This library is inspired by Haskells IntMap, which in turn implements Okasaki and Gill's Fast mergable integer maps.
As noted in the references, here are some runtimes:
O(min(n, W)): insert
, update
, remove
, get
, member
O(n + m): uniteWith
, union
, intersection
, diff
, merge
where n and m are the sizes of the first and second dictionary respectively and W
is the number of bits in Int
(so a constant with current value 32).
Dictionary equality with (==)
is unreliable and should not be used.
A dictionary mapping Int
s to values of a type v
. Analogous to
Dict Int v
.
isValidKey : Basics.Int -> Basics.Bool
Validates that a given integer is usable as a key.
This is necessary due to JavaScript's weird number type.
Basically this assures that we can use the functions
from Bitwise
without risking integer overflow.
This function is a necessity for sanitizing user input! Alternatively,
use the safe functions from IntDict.Safe
which perform the check for you.
As with the current version of JavaScript (2015), only 32 bit signed integers are supported. If this ever changes, contact me! Certain parts of the implementation depend on this!
empty : IntDict v
Create an empty dictionary.
singleton : Basics.Int -> v -> IntDict v
Create a dictionary with one key-value pair.
insert : Basics.Int -> v -> IntDict v -> IntDict v
Insert a key-value pair into a dictionary. Replaces value when there is a collision.
update : Basics.Int -> (Maybe v -> Maybe v) -> IntDict v -> IntDict v
Update the value of a dictionary for a specific key with a given function.
remove : Basics.Int -> IntDict v -> IntDict v
Remove a key-value pair from a dictionary. If the key is not found, no changes are made.
isEmpty : IntDict v -> Basics.Bool
Check if the dictionary contains no items.
size : IntDict v -> Basics.Int
The number of items in the dictionary. O(1)
.
member : Basics.Int -> IntDict v -> Basics.Bool
Determine if a key is in a dictionary.
get : Basics.Int -> IntDict v -> Maybe v
Get the value associated with a key. If the key is not found, return
Nothing
. This is useful when you are not sure if a key will be in the
dictionary.
before : Basics.Int -> IntDict v -> Maybe ( Basics.Int, v )
Find the key and value in the dictionary before the given key.
after : Basics.Int -> IntDict v -> Maybe ( Basics.Int, v )
Find the key and value in the dictionary after the given key.
findMin : IntDict v -> Maybe ( Basics.Int, v )
Find the minimum key and value in the dictionary.
findMax : IntDict v -> Maybe ( Basics.Int, v )
Find the maximum key and value in the dictionary.
uniteWith : (Basics.Int -> v -> v -> v) -> IntDict v -> IntDict v -> IntDict v
uniteWith merger l r
combines two dictionaries. If there is a collision, merger
is called with the conflicting key, the value from l
and that from r
.
union : IntDict v -> IntDict v -> IntDict v
Combine two dictionaries. If there is a collision, preference is given to the first dictionary.
intersect : IntDict a -> IntDict b -> IntDict a
Keep a key-value pair when its key appears in the second dictionary. Preference is given to values in the first dictionary.
diff : IntDict a -> IntDict b -> IntDict a
Keep a key-value pair when its key does not appear in the second dictionary.
merge : (Basics.Int -> a -> result -> result) -> (Basics.Int -> a -> b -> result -> result) -> (Basics.Int -> b -> result -> result) -> IntDict a -> IntDict b -> result -> result
The most general way of combining two dictionaries. You provide three accumulators for when a given key appears:
You then traverse all the keys from lowest to highest, building up whatever you want.
Note that uniteWith
, union
, intersect
and diff
could all be implemented
in terms of this function. The only reason that's not the case is to have more
sharing of substructure.
uniteWith merger l r =
merge insert merger insert l r empty
union l r =
merge insert (\k a _ d -> insert k a d) insert l r empty
intersect l r =
merge (\_ _ d -> d) (\k a _ d -> insert k a d) (\_ _ d -> d) l r empty
diff l r =
merge insert (\_ _ _ d -> d) (\_ _ d -> d) l r empty
keys : IntDict v -> List Basics.Int
Get all of the keys in a dictionary, sorted from lowest to highest.
values : IntDict v -> List v
Get all of the values in a dictionary, in the order of their keys.
toList : IntDict v -> List ( Basics.Int, v )
Convert a dictionary into an association list of key-value pairs, sorted by keys.
fromList : List ( Basics.Int, v ) -> IntDict v
Convert an association list into a dictionary.
map : (Basics.Int -> a -> b) -> IntDict a -> IntDict b
Apply a function to all values in a dictionary.
foldl : (Basics.Int -> v -> a -> a) -> a -> IntDict v -> a
Fold over the key-value pairs in a dictionary, in order from lowest key to highest key.
foldr : (Basics.Int -> v -> a -> a) -> a -> IntDict v -> a
Fold over the key-value pairs in a dictionary, in order from highest key to lowest key.
filter : (Basics.Int -> v -> Basics.Bool) -> IntDict v -> IntDict v
Keep a key-value pair when it satisfies a predicate.
partition : (Basics.Int -> v -> Basics.Bool) -> IntDict v -> ( IntDict v, IntDict v )
Partition a dictionary according to a predicate. The first dictionary contains all key-value pairs which satisfy the predicate, and the second contains the rest.
toString : IntDict v -> (v -> String) -> String
Generates a string representation similar to what toString
generates for Dict
. You must provide a function to convert
your value type into a string.