我需要练习帮助。我正在尝试编写一个名为“refer”的函数,该函数将使用引用([n])获取小说和任何给定文本的列表,并将返回该文本,并将引号替换为小说的名称。
参考将具有以下签名:
refer :: [(String, String, Int)] -> String -> String
例如,这就是它的运行方式:
> refer [("author1", "novel1", 1999),("author2", "novel2", 2000)] txt
> "novel1(author1, 1999) and novel2(author2, 2000) are my favorite books of all time, but I like novel2(author2, 2000) the most!"
我写了一个名为txt的函数,它将显示我将使用的文本。
txt :: String
txt = "[1] and [2] are my favorite books of all time, but I like [2] the most!"
我写了一个名为format的辅助函数,它将帮助我将小说格式从(“author1”,“novel1”,1999)格式化为“novel1(author1,1999)”
format :: (String, String, Int) -> String
format (name, novel, yearInt) = novel ++ " (" ++ name ++
", " ++ (show yearInt) ++ ")"
我认为我需要做什么:
步骤1:我需要使用单词将输入分解为字符串列表
第2步:我应该创建一个辅助函数来解析列表,如果我找到引文,我应该使用格式替换该引文并递归解析列表的其余部分,直到我检查了所有内容。
第3步:创建一个辅助函数,将引用数字的字符串表示转换为Int
(可能是unwords
),因为我必须将引文替换为给定列表中的相应元素。 />
第4步:然后我需要使用rewords
将我更新的列表转换回字符串。
我有多远:
refer :: [(String, String, Int)] -> String -> String
refer [] "" = ""
refer books txt = [string'| y <- words txt, ........... ]
-- I'm trying to say that I want to take the inputted list of
-- novels and text and turn them all into strings and store
-- them into y which will be represented by string'. I am not
-- sure what to do after this.
答案 0 :(得分:1)
您可以使用words
,但之后会丢失有关单词之间空白区域的信息 - 即words "a b"
等于words "a b"
。也许这并不重要,但要记住这一点。
如果没有提供确切的解决方案,这里有一个函数用 a&#39; 和 b 替换 a b&# 39; 在列表中:
replace a a' b b' [] = [] -- base case
replace a a' b b' (x:xs) = c : replace a a' b b' xs
where c = if x == a then a' else if x == b then b' else x
也许你可以弄清楚如何使这适应你的问题。
另请注意,此功能可以使用map
:
replace a a' b b' xs = map f xs
where f x = if x == a then a' else if x == b then b' else x
这种字符串处理的另一种方法是对字符进行模式匹配。这是一个删除所有&#34; cat&#34;来自一个字符串:
removeCat :: String -> String
removeCat ('c':'a':'t':rest) = rest -- "cat" found so remove it
removeCat (x:rest) = x : removeCat rest
答案 1 :(得分:0)
解决一般问题更容易。
首先,您需要replace
函数来替换子字符串。一个简单的实现可以是
replace :: String -> String -> String -> String
replace old new [] = []
replace old new input = if (take n input == old) then new++(recurse n)
else (take 1 input)++(recurse 1)
where n = length old
recurse k = replace old new $ drop k input
尝试匹配&#34; old&#34;从输入开始,如果匹配则替换并跳过旧的长度,如果不匹配则移动一个位置并重复。
到目前为止,这将取代所有出现的&#34; old&#34;到&#34;新&#34;。但是,您需要多个不同的替换。为此,让我们写另一个功能。为了最大限度地减少验证,我们假设我们将所有替换配对。
replaceAll :: [(String,String)] -> String -> String
replaceAll [] input = input
replaceAll ((old,new):xs) input = replaceAll xs $ replace old new input
您可以通过定义
等类型来更好地制作顶级签名type Novel = (String,String,Int)
最后,
refer :: [Novel] -> String -> String
refer [] text = text
refer ns text = replaceAll p text
where p = [ ("["++show i++"]",format n) | (i,n) <- zip [1..] ns]
注意引文输入来自小说的位置。