将属性文件加载到Map结构中

时间:2012-01-08 17:27:54

标签: haskell

我有一个类似Java的属性文本文件,带有键值对。将这些数据加载到haskell然后访问它的有什么好方法。

文件看起来像:

XXXX=vvvvv   
YYYY=uuuuu

我希望能够访问“XXXX”键。

2 个答案:

答案 0 :(得分:4)

您可以使用解析器库,例如优秀的Parsec(Haskell平台的一部分)。为简单的格式编写解析器只需几分钟。

然而,如果它真的那么简单,你可以使用split;使用标准lines函数将字符串拆分为行(如果需要处理空行等,则使用Data.List.Split),然后使用Data.List.Split函数将其拆分为{{ 1}}。

最简单的解决方案是使用break滚动自己:

'='

但是,这不会处理空格,空行或类似的内容。

至于按键查找,一旦你有import Control.Arrow parse :: String -> [(String, String)] parse = map parseField . lines where parseField = second (drop 1) . break (== '=') 之类的结构,很容易将它放入MapfromList)并对其进行操作。

答案 1 :(得分:1)

探索ehird未提及的一些细节,以及略有不同的方法:

import qualified Data.Map as Map

type Key = String
type Val = String

main = do
  -- get contents of file (contents :: String)
  contents <- readFile "config.txt"

  -- split into lines (optionList :: [String])
  let optionList = lines contents

  -- parse into map (optionMap :: Map Key Val)
  let optionMap = optionMapFromList optionList

  doStuffWith optionMap

optionMapFromList :: [String] -> Map.Map Key Val
optionMapFromList = foldr step Map.empty
  where step line map = case parseOpt line of
          Just (key, val) -> Map.insert key val map
          Nothing         -> map

parseOpt :: String -> Maybe (Key, Val)
parseOpt = undefined

我已经将您的问题解决方案表达为 fold :获取文件中的行列表,并将其转换为所需的地图。折叠的每个step包括检查单行,尝试将其解析为键/值对,并在成功时将其插入到地图中。

我离开parseOpt未定义;你可以使用像ehird parseField这样的方法,或者你喜欢的任何方法。也许你更愿意只解析特定的选项:

interestingOpts = ["XXXX", "YYYY"]

parseOpt line = case find (`isPrefixOf` line) interestingOpts of
  Just key -> Just (key, drop 1 $ dropWhile (/= '=') line)
  Nothing  -> Nothing

如果你有(例如)选项“XX”和选项“XXXX”,使用前缀测试方法并不总是最好的想法。四处游走,看看哪种方法最适合您的数据。如果您需要高性能,请使用Data.Text代替String s。