我有一个文本文件,如下所示:
ccc 1 1
bbb 2 2
aaa 3 3
我想创建一个函数,以这样的第一个单词获得整行:
f bbb = "bbb 2 2"
f aaa = "aaa 3 3"
我写了以下代码:
contents !! (fromJust (findIndex (name `isInfixOf`) contents))
contents
是包含上述文本的字符串列表。
读取文件并使用以下功能后:
all <- readFile file
contents <- lines all
它可以工作,但是看起来不太好。
是否有更直接的方法来执行功能f
(从上方)?
我认为Data.List.find
或Data.Text.find
可能会有所帮助,但它们似乎不匹配。
答案 0 :(得分:1)
为什么不过滤前缀上的行?
Prelude> contents = lines "ccc 1 1\nbbb 2 2\naaa 3 3"
Prelude> import Data.List
Prelude Data.List> f prefix = head $ filter (isInfixOf prefix) contents
Prelude Data.List> f "aaa"
"aaa 3 3"
Prelude Data.List> f "abc"
"*** Exception: Prelude.head: empty list
如果希望所有匹配的行(可能为空列表),则可以删除head
。
如果您想多次使用f,则地图将具有更好的性能,但前提是您只查找行,因为该行的第一个单词(且没有任何前缀):< / p>
Prelude> contents = lines "ccc 1 1\nbbb 2 2\naaa 3 3"
Prelude> import Data.Map (fromList, (!))
Prelude Data.Map> m = fromList $ zip =<< (map $ head.words) $ contents
Prelude Data.Map> m!"aaa"
"aaa 3 3"
Prelude Data.Map> m!"abc"
"*** Exception: Map.!: given key is not an element in the map
CallStack (from HasCallStack):
error, called at libraries/containers/Data/Map/Base.hs:489:16 in containers-0.5.7.1:Data.Map.Base
运算符(!)
将在列表版本的 O(log n)与 O(n)中找到值。
一些解释:
fromList
创建一个给定(key, value)
列表的地图map $ head.words
接受列表中每个元素的第一个单词(zip =<< g) contents
等效于zip (g contents) contents
(在这里:将第一个单词用行压缩)