我正在尝试编写一个函数,该函数采用第一个字符串的第一个字符,将其与第二个字符串的所有字符进行比较,如果找到相同的字符,则将其替换为“-”。然后,它移至第一个字符串的第二个字符,对第二个字符串上的每个字符(除了第一个字符-我们已经检查过的那个字符)进行相同的比较,依此类推。我希望它返回第一个字符串,但是将重复的字符替换为符号“-”。
例如如果我输入comparing "good morning" "good afternoon"
,我希望它返回"-----m---i-g"
我希望我解释得足够清楚。到目前为止,我已经:
comparing :: String -> String -> String
comparing a b =
if a == "" then ""
else if head a == head b then "-" ++ (comparing (tail a) (tail b))
else [head a] ++ (comparing (tail a) b)
问题是它不会逐个字符地通过第二个字符串,而且我不确定如何实现。我想我需要在第四行调用递归函数:
if head a == ***the first character of tail b*** then "-" ++ (comparing (tail a) (tail b))
该功能看起来像什么?还是有更好的方法来做到这一点?
答案 0 :(得分:3)
首先,在每个递归调用中,当您遍历字符串a
时,出于某种原因,您同时也在遍历字符串b
。看:您仅将tail b
传递给下一个呼叫。这意味着下一个调用将无法通过整个字符串b
进行查看,而只能通过其尾部进行查看。你为什么要这样做?
第二,为了查看字符串中是否存在字符,请使用elem
:
elem 'x' "xyz" == True
elem 'x' "abc" == False
因此,函数的第二行应如下所示:
else if elem (head a) b then "-" ++ (comparing (tail a) b)
在某种程度上相关的注释上,head
和tail
函数的使用有些皱眉,因为它们是局部的:如果字符串为空,它们将崩溃。是的,我发现您已经检查过以确保该字符串为 not 为空,但是编译器无法理解该字符串,这意味着当您不小心更改字符串时,它将无法捕获您以后再检查。
检查数据的更好方法是通过模式匹配:
-- Comparing an empty string with anything results in an empty string
comparing "" _ = ""
-- Comparing a string that starts with `a` and ends with `rest`
comparing (a:rest) b =
(if elem a b then "-" else a) ++ comparing rest b
答案 1 :(得分:1)
这看起来像手动map
的经典用例,而不是手动编写递归逻辑。您只需要一个函数,该函数需要一个字符并根据另一个列表中的字符来返回该字符或'-'
。
完全写出来,看起来像这样:
comparing first second = map replace first
where replace c = if c `elem` second then '-' else c