owanturist / elm-avl-dict / AVL.Dict

An AVL Tree based dictionary.

A dictionary mapping unique keys to values. The keys can be any type. This includes both custom and comparable types such as Int, Float, Time, Char, String, and tuples or lists of comparable types.

Insert, remove, get and member operations all take O(log n) time. Size takes constant O(1) time.

Dictionary


type alias Dict key value =
Internal.AVLDict key value

A dictionary of keys and values. So a Dict String User is a dictionary that lets you look up a String (such as user names) and find the associated User.

import AVL.Dict as Dict exposing (Dict)

users : Dict String User
users =
    Dict.fromList
        [ ( "Alice", User "Alice" 28 1.65 )
        , ( "Bob", User "Bob" 19 1.82 )
        , ( "Chuck", User "Chuck" 33 1.75 )
        ]

type alias User =
    { name : String
    , age : Int
    , height : Float
    }

Construction


type alias Comparator key =
key -> key -> Basics.Order

A comparator is a function which compares two keys. So a Dict ID User is a dictionary that lets you look up a ID (such as user ids) and find the associated User.

import AVL.Dict as Dict exposing (Comparator, Dict)

type ID
    = ID Int

compareID : Comparator ID
compareID (ID x) (ID y) =
    compare x y

users : Dict ID User
users =
    Dict.fromListWith compareID
        [ ( ID 0, User (ID 0) "Alice" 28 1.65 )
        , ( ID 1, User (ID 1) "Bob" 19 1.82 )
        , ( ID 2, User (ID 2) "Chuck" 33 1.75 )
        ]

alice : Maybe User
alice =
    Dict.get (ID 0) users

type alias User =
    { id : ID
    , name : String
    , age : Int
    , height : Float
    }

empty : Dict comparable value

Create an empty dictionary with comparable keys.

emptyWith : Comparator key -> Dict key value

Create an empty dictionary with custom keys.

singleton : comparable -> value -> Dict comparable value

Create a dictionary with one comparable key-value pair.

singletonWith : Comparator key -> key -> value -> Dict key value

Create a dictionary with one custom key-value pair.

fromList : List ( comparable, value ) -> Dict comparable value

Convert an association list into a dictionary with comparable keys.

fromListWith : Comparator key -> List ( key, value ) -> Dict key value

Convert an association list into a dictionary with custom keys.

Deconstruction

keys : Dict key value -> List key

Get all of the keys in a dictionary, sorted from lowest to highest.

Dict.keys (Dict.fromList [ ( 1, "Bob" ), ( 0, "Alice" ) ]) == [ 0, 1 ]

values : Dict key value -> List value

Get all of the values in a dictionary, in the order of their keys.

Dict.values (Dict.fromList [ ( 1, "Bob" ), ( 0, "Alice" ) ]) == [ "Alice", "Bob" ]

toList : Dict key value -> List ( key, value )

Convert a dictionary into an association list of key-value pairs, sorted by keys.

Dict.toList (Dict.fromList [ ( 1, "Bob" ), ( 0, "Alice" ) ]) == [ ( 0, "Alice" ), ( 1, "Bob" ) ]

Manipulation

insert : key -> value -> Dict key value -> Dict key value

Insert a key-value pair into a dictionary. Replaces value when there is a collision.

remove : key -> Dict key value -> Dict key value

Remove a key-value pair from a dictionary. If the key is not found, no changes are made.

update : key -> (Maybe value -> Maybe value) -> Dict key value -> Dict key value

Update the value of a dictionary for a specific key with a given function.

clear : Dict key value -> Dict key value

Remove all entries from a dictionary. Useful when you need to create new empty dictionary using same comparator.

Query

isEmpty : Dict key value -> Basics.Bool

Determine if a dictionary is empty.

size : Dict key value -> Basics.Int

Determine the number of key-value pairs in the dictionary. It takes constant time to determine the size.

member : key -> Dict key value -> Basics.Bool

Determine if a key is in a dictionary.

get : key -> Dict key value -> Maybe value

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.

animals =
    Dict.fromList [ ( "Tom", Cat ), ( "Jerry", Mouse ) ]

Dict.get "Tom" animals == Just Cat
Dict.get "Jerry" animals == Just Mouse
Dict.get "Spike" animals == Nothing

minimum : Dict key value -> Maybe ( key, value )

Get the key-value pair associated with minimum key. If Dict is empty return Nothing.

import AVL.Dict as Dict exposing (Dict)

type alias User =
    { name : String
    , age : Int
    , height : Float
    }

users : Dict String User
users =
    Dict.fromList
        [ ( "Bob", User "Bob" 19 1.82 )
        , ( "Alice", User "Alice" 28 1.65 )
        , ( "Chuck", User "Chuck" 33 1.75 )
        ]

Dict.minimum users == Just ( "Alice", User "Alice" 28 1.65 )

maximum : Dict key value -> Maybe ( key, value )

Get the key-value pair associated with maximum key. If Dict is empty return Nothing.

import AVL.Dict as Dict exposing (Dict)

type alias User =
    { name : String
    , age : Int
    , height : Float
    }

users : Dict String User
users =
    Dict.fromList
        [ ( "Bob", User "Bob" 19 1.82 )
        , ( "Alice", User "Alice" 28 1.65 )
        , ( "Chuck", User "Chuck" 33 1.75 )
        ]

Dict.maximum users == Just ( "Chuck", User "Chuck" 33 1.75 )

Transform

map : (key -> a -> b) -> Dict key a -> Dict key b

Apply a function to all values in a dictionary.

filter : (key -> value -> Basics.Bool) -> Dict key value -> Dict key value

Keep only the key-value pairs that pass the given test.

partition : (key -> value -> Basics.Bool) -> Dict key value -> ( Dict key value, Dict key value )

Partition a dictionary according to some test. The first dictionary contains all key-value pairs which passed the test, and the second contains the pairs that did not.

foldl : (key -> value -> acc -> acc) -> acc -> Dict key value -> acc

Fold over the key-value pairs in a dictionary from lowest key to highest key.

foldr : (key -> value -> acc -> acc) -> acc -> Dict key value -> acc

Fold over the key-value pairs in a dictionary from highest key to lowest key.

Combine

union : Dict key value -> Dict key value -> Dict key value

Combine two dictionaries. If there is a collision, preference is given to the left dictionary.

diff : Dict key value -> Dict key value -> Dict key value

Keep a key-value pair when its key does not appear in the right dictionary.

intersect : Dict key value -> Dict key value -> Dict key value

Keep a key-value pair when its key appears in the right dictionary. Preference is given to values in the left dictionary.

merge : (key -> left -> acc -> acc) -> (key -> left -> right -> acc -> acc) -> (key -> right -> acc -> acc) -> Dict key left -> Dict key right -> acc -> acc

The most general way of combining two dictionaries. You provide three accumulators for when a given key appears:

  1. Only in the left dictionary.
  2. In both dictionaries.
  3. Only in the right dictionary.

You then traverse all the keys from lowest to highest, building up whatever you want.