逐行搜索 .txt 文件 Haskell

马特G

我是 Haskell 的新手,我创建了一个函数来允许“用户”将新电影添加到数据库(一个名为 Films.txt 的文本文件)。

main = do
    putStrLn "Insert film title:"
    film <- getLine
    putStrLn ("Who directed " ++ film ++ "?")
    director <- getLine
    putStrLn ("What year was " ++ film ++ " released?")
    year <- getLine
    appendFile "Films.txt" $ (film ++ "\n")
    appendFile "Films.txt" $ (director ++ "\n")
    appendFile "Films.txt" $ (year ++ "\n")
    appendFile "Films.txt" $ (" " ++ "\n")

创建的文本文件的一个例子是:

Blade Runner
Ridley Scott
1982
The Fly
David Cronenberg
1986
etc...

如果我只想返回某个导演的电影,我将如何逐行搜索该文件。在另一种语言中,我将使用 FOR 循环逐行搜索 .txt 文件,直到有一行与搜索词匹配,例如“Ridley Scott”。然后我将返回到匹配行上方的行,输出它(电影名称)并继续搜索,直到 .txt 文件完成。

但是在 Haskell 中,我无法将这个思维过程转换为代码,主要是因为我找不到逐行搜索文件的方法。

谢谢

双头

使用您自己的方法,扫描文件以查找名称:

main = do
    putStrLn "Enter Director's name"
    name <- getLine
    base <- readFile "Films.txt"     -- base is the whole file contents as a single string
    print $moviesBy name $lines base

moviesBy :: String -> [String] -> [[String]]
moviesBy name (title:director:year:_:others) | director == name = [title, director, year]:moviesBy name others
                                             | otherwise = moviesBy name others -- a different director, scan the rest of the file
moviesBy _ _ = [] -- when there's no more records

更详细...

lines base 将文件内容按行拆分(删除换行符),生成字符串列表。

moviesBy接受字符串作为搜索模式,以及作为文件内容的字符串列表。从这个文件是如何创建的,我们希望在每一个找到导演的名字第二行每四。这是作为第一个模式匹配完成的:

moviesBy name (title:director:year:_:others)

在这里,(title:director:year:_:others)匹配一个至少包含四个元素的列表,将它们绑定到相关变量(_第四个位置是一个通配符模式,这里与对我们无关紧要的空白字符串进行匹配)。others,作为 最右边的操作数:,因此匹配列表的剩余部分(第四个尾部,用 Lisp 的话)。在管道之后,|我们在匹配上添加了一个额外的约束,四元组中的第二个元素应该等于关注的导演的名字。如果为 true,则将 的列表[title, director, year]插入输出中(作为 的:RHS 上的左操作数,=产生式规则的右侧部分),并other通过递归调用检查列表 ( )的其余部分(右侧该 RHS 的操作数:);otherwise 这个四元组被跳过,只考虑剩下的部分。

最后一行中的匹配处理任何少于四个元素的列表(这可能是文件的结尾)。由于我们不太可能在如此短的列表中找到更多导演的电影,我们只需返回[]

因此,例如,如果我们有一个列表

["Blade Runner", "Ridley Scott", "1982", " ", "Alien", "Ridley Scott", "1979", " "]

然后寻找斯科特的电影,我们得到:

  1. 首先, list 与(title:director:year:_:others). 然后绑定变量:title是“银翼杀手”,director是“雷德利斯科特”,year是“1982”,others["Alien", "Ridley Scott", "1979", " "]. 由于director等于我们正在寻找的名称,我们采用第一条路径并宣布["Blade Runner", "Ridley Scott", "1982"]:moviesBy "Ridley Scott" ["Alien", "Ridley Scott", "1979", " "]为我们的结果。

  2. 接下来,递归调用以构造结果列表的尾部。这里再次title是“Alien”,director“Ridley Scott”,year是“1979”并且others绑定到一个空列表。因此,步骤 1. 的结果列表的尾部是["Alien", "Ridley Scott", "1979"]:moviesBy "Ridley Scott" []

  3. 最后一次递归调用。我们不能将至少四个元素模式绑定到空列表,因此我们采用最后一个选项,moviesBy _ _匹配字符串和列表的任意组合,这里的结果是 [](递归停止)。因此,步骤 2. 的结果是["Alien", "Ridley Scott", "1979"]:[],换句话说,[["Alien", "Ridley Scott", "1979"]]并且在 1. 中添加 head ,该函数的总结果是[["Blade Runner", "Ridley Scott", "1982"], ["Alien", "Ridley Scott", "1979"]]

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章