wvogel日記

自分用の技術備忘録が多めです.

Data.Array

以前に一度Data.Arrayについて記事を書いたことがあったが、
その時は基本的な関数について触れただけで終わった気がする。

今回は、二次元配列を触ってみた。

とりあえず、1桁の数で作られたテーブルから値を読み取る。

ソースコードは以下のとおり

import Data.Array

type ArrayI = Array Int Int
type ArrayII = Array Int ArrayI

makeRange :: String -> (Int,Int)
makeRange = (\[a,b] -> (a,b)).map read.take 2.words

makeArray :: (Int,Int) -> IO ArrayII
makeArray (h,w)
 = do cs <- getContents
      let xs = take h $ lines cs
      return $ array (1,h) $ zip [1..h]
                           $ map (makeArray' w) xs

makeArray' :: Int -> String -> ArrayI
makeArray' w str = array (1,w) $ zip [1..w] $ map f str
  where
    f c = read [c]

--配列からindex(h',w')の要素を見る
seeValue :: Int -> Int -> ArrayII -> Int
seeValue h' w' mapData = (mapData ! h') ! w'

main = do hw <- getLine
          mapData <- makeArray.makeRange $ hw
          print mapData
          print $ seeValue 2 3 mapData


実行結果

$ ./array
4 4
1234
5678
1248
7777
array (1,4)
 [(1,array (1,4) [(1,1),(2,2),(3,3),(4,4)]),
  (2,array (1,4) [(1,5),(2,6),(3,7),(4,8)]),
  (3,array (1,4) [(1,1),(2,2),(3,4),(4,8)]),
  (4,array (1,4) [(1,7),(2,7),(3,7),(4,7)])]
7

二次元配列を扱うため、見やすいように型をtype宣言で省略しています。
まず一次元配列を作り、
それをさらに、与えられた範囲で
Array (i,Array Int Int)
の形の配列に落とし込みます。
そのために、要素へのアクセスはC言語同様、直感的。

まあただ、やはりCなどに比べると配列の準備が面倒ですね。
あと、これは以前にも書いたと思いますが、
配列の中身を更新する際にはHaskellの場合全ての値を更新するので、そのような動作はリストを使うようにしましょう。