Haskell-通过前缀在列表中查找字符串

时间:2018-12-16 15:09:04

标签: haskell

我有一个文本文件,如下所示:

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.findData.Text.find可能会有所帮助,但它们似乎不匹配。

1 个答案:

答案 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(在这里:将第一个单词用行压缩)