今週のお題「2018年の抱負」
Data.Map
の話
連想リストを使う
をMapを使う
ということにする。Data.Map
はキーが順序付けされていることを利用して、効率よくキーを配置したりキーにアクセスしたりできる。
Data.Map
はPrelude
やData.List
と競合する名前をエクスポートしているので修飾付きインポートを行う。
import qualified Data.Map as Map
Data.Map.fromList
を使って連想リストをMap
に変換する
*Main> Map.fromList [(3,"shoes"),(4,"trees"),(9,"bees")] fromList [(3,"shoes"),(4,"trees"),(9,"bees")]
元の連想リストに同じキーがあった場合は後のほうの要素が使われる。
連想リストをMap
で実装する
phoneBook :: Map.Map String String phoneBook = Map.fromList $ [("betty", "555-2938") ,("bonnie1", "334-8878") ,("bonnie2", "334-8878") ,("bonnie3", "334-8878") ,("bonnie4", "334-8878") ]
実行結果
*Main> Map.lookup "betty" phoneBook Just "555-2938"
phoneBook
に新しい電話番号を挿入して新しいMapを作る
*Main> :t Map.insert Map.insert :: Ord k => k -> a -> Map.Map k a -> Map.Map k a *Main> Map.lookup "foo" phoneBook Nothing *Main> let newBook = Map.insert "foo" "123-5678" phoneBook *Main> Map.lookup "foo" newBook Just "123-5678"
電話番号がいくつあるか調べる
*Main> :t Map.size Map.size :: Map.Map k a -> Int *Main> Map.size phoneBook 5 *Main> Map.size newBook 6
電話番号を文字列でなく、Int のリストで表現したい。
string2digits :: String -> [Int] string2digits = map digitToInt . filter isDigit
実行結果
*Main> string2digits "123-5678" [1,2,3,5,6,7,8]
phoneBook に適用する
*Main> let intBook = Map.map string2digits phoneBook *Main> :t intBook intBook :: Map.Map String [Int] *Main> Map.lookup "betty" intBook Just [5,5,5,2,9,3,8]
1人が複数の電話番号を持っている場合に対応する。
phoneBook = Map.fromList $ [("betty", "555-2938") ,("bonnie1", "334-8878") ,("bonnie1", "334-8877") ,("bonnie1", "334-8876") ,("bonnie1", "334-8875") ,("bonnie2", "334-8878") ,("bonnie3", "334-8878") ,("bonnie3", "335-8878") ,("bonnie4", "334-8878") ]
これだと、重複しているキーのペアは最後の要素が優先されてしまう。
*Main> phoneBook fromList [("betty","555-2938"),("bonnie1","334-8875"),("bonnie2","334-8878"),("bonnie3","335-8878"),("bonnie4","334-8878")]
この問題を解決するにはData.Map.fromListWith
を使う。この関数はキーの重複を削除しない。そのかわり、重複していた場合にどうするか決める関数を受け取る。
phoneBookToMap :: (Ord k) => [(k, String)] -> Map.Map k String phoneBookToMap xs = Map.fromListWith add xs where add number1 number2 = number1 ++ ", " ++ number2
実行結果
*Main> Map.lookup "bonnie1" $ phoneBookToMap phoneBook Just "334-8875, 334-8876, 334-8877, 334-8878"
所感
編集途中で投稿してしまってた。

- 作者: MiranLipovaca
- 出版社/メーカー: オーム社
- 発売日: 2017/07/14
- メディア: Kindle版
- 購入: 4人 クリック: 9回
- この商品を含むブログを見る