如何过滤文本文件Haskell中不需要的单词

Mar*_*n V -2 haskell

我正在尝试在Haskell中编写一个可以从文本文档中过滤掉不需要的关键字的程序.文本文档包含有关人员的信息,例如姓名,年龄和城市,我想过滤掉与不符合关键字的人相关的所有信息.

数据库看起来像这样:

"Eric" 27 "London"
"Josefine" 34 "Stockholm"
"Hans" 50 "London"
Run Code Online (Sandbox Code Playgroud)

所以如果关键字是"伦敦",我想要以下输出:

"Eric" 27 "London"
"Hans" 50 "London"
Run Code Online (Sandbox Code Playgroud)

我已经尝试了一些不同的方法来存储信息并过滤掉不需要的人,但我现在对如何做到这一点毫无头绪.

Ben*_*son 5

只需使用Prelude中的点点滴滴即可完成此练习.首先让我们将您的文本解析为更有条理的内容:

data Person = Person {
    personName :: String,
    personAge :: Int,
    personLocation :: String
}

parse :: String -> [Person]
parse txt = let rows = map words (lines txt)
            in map (\[name, age, location] -> Person name (read age) location) rows
Run Code Online (Sandbox Code Playgroud)

我正在使用神奇的力量map :: (a -> b) -> [a] -> [b]深入研究所产生的列表lines.我正在映射它的lambda函数是部分的 - 如果任何输入行的格式不正确,它将使程序崩溃.在现实世界的代码中,我肯定会通过在我的解析器中构建错误处理来更优雅地处理故障:我将返回类型更改为Either String [Person]并返回,Left "an error message"如果它无法解析.像Parsec这样的解析器库提供开箱即用的错误处理.

现在我们可以直截了当地filter :: (a -> Bool) -> [a] -> [a]说出我们不感兴趣的人.

londonPeople :: [Person] -> [Person]
londonPeople = filter (\p -> personLocation p == "London")
Run Code Online (Sandbox Code Playgroud)

打印输出也很简单:

personToString :: Person -> String
personToString (Person name age location) = unwords [name, show age, location]
Run Code Online (Sandbox Code Playgroud)

我们可以将这些碎片整合到一个程序中:

input = "Eric 27 London\nJosefine 34 Stockholm\nHans 50 London"

main = let people = parse input
           output = map personToString (londonPeople people)
       in putStrLn (unlines output)
Run Code Online (Sandbox Code Playgroud)

运行它会产生预期的输出.

$ runhaskell people.hs
Eric 27 London
Hans 50 London
Run Code Online (Sandbox Code Playgroud)