indique/elm-keysdict

lookup values by many keys


Keywords
multiway, multikey, multiway-dict
License
MIT
Install
elm-package install indique/elm-keysdict 2.0.3

Documentation

Moved to lue-bird/elm-keysset

Β 

KeysDict

Have many keys to lookup values.

Let's compare

normal Dict

You want the value where the key is 1?

    0 :  🏑
--> 1 :  🏚
    2 :  🏚

the key is unique among all items

Going through while comparing your key.

the value is 🏚  where the key is `1`

KeysDict

First of all, get used to some names

  • a "house" contains aspects that make it unique & aspects that can be shared across all houses
keepInParserPipelineOperator=
  { operator= "|=" --only one operator should have this symbol!
  , origin= ElmRepoPackage "parser" --is the same for |.
  }
  • a "door" describes a unique aspect across all houses.
door .operator
--is a promise, that the operator value is never the same for two houses.

So... If you have a key and the type of door it could match, you can find the only matching house and enter.

You want to enter the house where πŸ—οΈ is 1?

    πŸ”‘= 0, 🏠= 🏚, πŸ—οΈ= 2
    πŸ”‘= 2, 🏠= 🏑, πŸ—οΈ= 0
    πŸ”‘= 1, 🏠= 🏚, πŸ—οΈ= 1 <--

πŸ”‘, πŸ—οΈ: doors you can "open" with a key unique across all houses

Going through while checking every house, if the πŸ—οΈ matches.

    πŸ”‘= 1, 🏠= 🏚, πŸ—οΈ= 1  where πŸ—οΈ is 1   

You want to enter the house where πŸ”‘ is 0?

--> πŸ”‘= 0, 🏠= 🏚, πŸ—οΈ= 2
    πŸ”‘= 2, 🏠= 🏑, πŸ—οΈ= 0
    πŸ”‘= 1, 🏠= 🏚, πŸ—οΈ= 1

πŸ”‘, πŸ—οΈ: doors you can "open" with a key unique across all houses

Going through while checking every house, if the πŸ”‘ matches.

    πŸ”‘= 0, 🏠= 🏚, πŸ—οΈ= 2  where πŸ”‘ is 0

Β 

πŸ‘ How to KeysDict

Try the ellie for some examples (always a version behind).

Example: cased letters

type alias CasedLetter=
  { lowercase: Char
  , uppercase: Char
  }

lowerUppercaseLetters: KeysDict CasedLetter
lowerUppercaseLetters=
  KeysDict.enterableBy
    [ door .lowercase, door .uppercase ]
  |>putUp { lowercase= 'a', uppercase= 'A' }
  |>putUp { lowercase= 'b', uppercase= 'B' }
  |>putUp { lowercase= 'c', uppercase= 'C' }

uppercase char=
  lowerUppercaseLetters
  |>enterBy { door= .lowercase, key= char }
  |>Maybe.map .uppercase

A word on imports

It's recommended to

import KeysDict.Uniqueness exposing (door)
import KeysDict exposing
  ( KeysDict
  , houses, enterBy
  , putUp, tearDown
  , foldHouses, countHouses --only if you use them
  )

They avoid clutter and shouldn't cause name conflicts.

Example: periodic table

type Element=
  Hydrogen
  | Helium

elementAtomicNumberKeysDict=
  KeysDict.enterableBy
    [ door .atomicNumber, door .element ]
  |>putUp { element= Hydrogen, atomicNumber= 1 }
  |>putUp { element= Helium, atomicNumber= 2 }

atomicNumberByElement=
  KeysDict.toDict { key= .element, value= .atomicNumber }
    elementAtomicNumberKeysDict

Example: brackets

brackets=
  KeysDict.enterableBy
    [ door .opening, door .closing ]
  |>putUp { opening= '(', closing= ')' }
  |>putUp { opening= '{', closing= '}' }

typeChar character=
  case access { door= .open, key= character } brackets of
    Just { closed }->
      String.fromValues [ character, closed ]

    Nothing->
      case access { door= .closed, key= character } brackets of
        Just { open }->
          String.fromValues [ open, character ]
          
        Nothing->
          String.fromChar character

"Typing (: " ++(typeChar '(') ++". Even }: " ++(typeChar '}')

Β 

πŸ‘Ž How not to KeysDict

Example: automatic answers

answers=
  KeysDict.enterableBy [ door .youSay ]
  |>putUp { youSay= "Hi", answer= "Hi there!" }
  |>putUp { youSay= "Bye", answer=  "Ok, have a nice day and spread some love." }
  |>putUp { youSay= "How are you", answer= "I don't have feelings :(" }
  |>putUp
      { youSay= "Are you a robot"
      , answer= "I think the most human answer is 'Haha... yes'"
      }

Please use a Dict where it is more appropriate: Dicts are for one-way access.

Example: translation, synonymes...

englishGerman=
  KeysDict.enterableBy []
  |>putIn { english= "elm", german= "Ulme" }
  |>putIn { english= "git", german= "Schwachkopf" }
  |>putIn { german= "RΓΌste", english= "elm" }

A KeysDict is only effective, when there is only one unique key for each door.

Please take a look at elm-bidict instead!

Example: partners, opposites...

Similar to the previous example:

partners=
  KeysDict.enterableBy
    [ door .partner, door .partnerOfPartner ]
  |>putUp { partner= "Ann", partnerOfPartner= "Alan" }
  |>putUp { partner= "Alex", partnerOfPartner= "Alastair" }
  |>putUp { partner= "Alan", partnerOfPartner= "Ann" }
      --wait, this is no duplicate and is inserted

A KeysDict ony makes sense, when the keys describe something different.