我想输入两个字符串,"你好"以及";嗨"例如,我想同时遍历两个字符串中的每个元素,并逐一比较每个字符。实际程序中的两个字符串长度应为5,如果一个字符等于另一个字符,则返回true,否则返回false。
我脑海中的程序应该在"H"中看到"H";你好"和来自"H"的"H";嗨"并返回true,则我希望它检查"e"中的"e";你好"以及"i"中的"i";嗨"并返回false。我希望它继续这样做,直到没有什么可比的了。我想我可能需要使用递归,但我不确定如何在这个程序中实现它。
我尝试使用最大范围为5的x:xs
,所以使用[0..5]
,但根本不起作用。
我的代码(不工作(:
uncurryingString :: String -> Int -> Char
uncurryingString a b = a !! b
match :: String -> String -> [Int] -> Bool
match a b (x:xs)
| uncurryingString a [x+1 | x <- xs] == uncurryingString b [x+1 | x <- xs] = True
| otherwise = False
您认为这种方式太复杂了。
首先,根据经验,您应该永远不要使用!!
(无论是直接使用还是通过一些助手使用——uncurryingString
实际上与!!
本身完全相同(。如果需要直接索引,则列表不是正确的数据结构。但通常情况下,直接索引不是所必需的,它只是其他一些编程语言中通常使用的,这些语言没有模式匹配来更优雅地进行索引。
在您的应用程序中,您正在并行地解构这两个字符串。好吧,你应该用模式匹配来表达这一点:
match (a:as) (b:bs) (x:xs) = ...
现在,您可以简单地直接比较a
和b
,而不需要麻烦任何列表理解或索引运算符。在示例输入"Hello"
和"Hi"
中,这里a
和b
都将是'H'
。
但是您可能不想直接返回True
,因为还有字符串的其余部分需要匹配。这就是递归的用武之地
最后,如果不是所有的输入列表都是非空的,则需要使用to子句。试着自己弄清楚。
您可能根本不需要额外的[Int]
参数(x:xs)
。它可能有一个深度限制参数是有意义的,但这可能只是一个Int
。然后你会做一些类似的事情
match :: Eq a => [a] -> [a] -> Int -> Bool
match _ _ 0 = True -- lists are equal up to the specified max depth
match (a:as) (b:bs) n = ...
...
在Haskell中使用列表理解通常是计算事物的好方法,但在这种特殊情况下不是。
我可以试试这个代码:
[a==b | a <- "Hello", b <- "Hi"]
这是干什么的?你可能认为这会返回True,因为"H"字母匹配——或者你可能认为它会返回False,因为其他字母不匹配。事实上,它同时做到了这两件事——实际上,它正在运行多个嵌套循环。
[True,False,False,False,False,False,False,False,False,False]
因此,当您想要嵌套循环或只处理一个数据集时,需要使用列表理解。在这里,我们只需要一个并行处理这两个单词的循环。因此它必须是递归的。