【问题标题】:How can I go through a list of numbers and compare it with an another list I am going through?如何浏览数字列表并将其与我正在浏览的另一个列表进行比较?
【发布时间】:2022-02-03 18:30:10
【问题描述】:

我想输入两个字符串,例如“Hello”和“Hi”,我想同时遍历两个字符串中的每个元素,并逐个比较每个字符。实际程序中两个字符串的长度应该是5,如果一个char相等,返回true,否则返回false。

我想到的程序应该在“Hello”中看到“H”,在“Hi”中看到“H”并返回真,然后我希望它检查“Hello”中的“e”和“Hello”中的“i” “嗨”并返回假。我希望它继续这样做,直到没有什么可比较的。我想我可能需要使用递归,但我不确定如何在这个程序中真正实现它。

我尝试使用最大范围为 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 

【问题讨论】:

  • 我对你的问题有点困惑,因为你说“实际程序中的两个字符串长度应该是 5”,但是“Hello”和“Hi”显然没有相同的长度.
  • 除了两个字符串之外,将数字列表传递给match 函数有什么意义?
  • 提供 2 个输入和预期输出的清晰示例可能有助于澄清问题。
  • @Julia 我很抱歉!我使用了它们,因为它们看起来很简单,在程序中它可能类似于“Hello”和“Horse”。很抱歉因为我没有解释而造成的混乱!

标签: haskell


【解决方案1】:

你想这种方式太复杂了。

首先,根据经验,您应该永远不要使用!!(无论是直接使用还是通过一些帮助程序——uncurryingString 实际上与!! 本身完全相同)。如果需要直接索引,则列表不是正确的数据结构。但通常不需要直接索引,它只是在其他一些没有模式匹配的编程语言中习惯使用的方式来更优雅地做到这一点。

在您的应用程序中,您正在并行解构两个字符串。好吧,你应该用模式匹配来表达:

match (a:as) (b:bs) (x:xs) = ...

现在您可以直接比较ab,无需搞乱任何列表推导或索引运算符。在示例输入 "Hello""Hi" 中,ab 在此处将是 'H'

但您可能不想在此处返回True,因为还有字符串的其余部分要匹配。这就是递归的用武之地。

最后,如果不是所有输入列表都是非空的,您需要使用子句。试着自己弄清楚。

您可能根本不需要额外的[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 = ...
...

【讨论】:

  • 感谢您非常有见地的回答。不过我有一个问题,看起来你仍然保留了 Int,这意味着我仍然需要它。如果我不使用索引运算符,它有什么用?我将如何操纵它?
  • 我的意思是,这取决于你想要完成什么。如果您想比较整个列表,无论它们有多长,那么您不需要任何 Int 参数。 (但是你也许应该在整个列表中使用 == ......)如果你想在一定深度后中止,例如不比较每个列表中超过 5 个元素,然后您可以使用该参数并在每个递归调用中递减它。 (但同样可以通过无限比较来实现,并且事先使用take简单地将列表修剪到所需的最大深度。
  • 感谢您的帮助!我已经使用我之前制作的功能进行了修剪,并且在所有内容中只使用了 5 个字符。所以我想我会尝试删除Int 参数。我会在整个列表中使用==,但我想逐个字符地比较它以查看字符是否匹配。据我了解,如果我使用==,它将检查两个字符串是否相同,如果我说的完全错误,请纠正我。再次感谢!
  • zipWith (==) "Hello" "Hi" 怎么样?
  • 我还是建议您将完整的手动递归版本(有和没有深度限制)作为练习。
【解决方案2】:

使用列表推导式通常是在 Haskell 中计算事物的好方法,但在这种特殊情况下并非如此。

我可以试试这个代码:

 [a==b | a <- "Hello", b <- "Hi"]

这是做什么的?您可能会认为这会返回 True,因为“H”字母匹配 - 或者您可能会认为这会返回 False,因为其他字母不匹配。事实上,它两者兼而有之 - 实际上,它正在运行多个嵌套循环。

[True,False,False,False,False,False,False,False,False,False]

因此,当您需要嵌套循环或只处理一个数据集时,要点是使用列表推导式。在这里,我们只需要一个并行处理两个单词的循环。因此它必须是递归的。

【讨论】:

  • 在您的回答中提及 and 函数可能是个好主意
  • 我认为 OP 想要的实际上是并排消费列表,而不是所有组合。不能用标准的列表理解来完成,但可以通过先压缩列表[a==b | (a,b) &lt;- zip "Hello" "Hi"] 或使用-XParallelListComp 扩展作为[a==b | a &lt;- "Hello" | b &lt;- "Hi"]
猜你喜欢
  • 2017-12-23
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多