【问题标题】:How can I find the index where one list appears as a sublist of another?如何找到一个列表作为另一个列表的子列表出现的索引?
【发布时间】:2015-04-08 13:46:58
【问题描述】:

我已经使用 Haskell 一个多星期了,所以我正在练习一些可能对某些事情有用的函数。我想递归地比较两个列表。当第一个列表出现在第二个列表中时,我只想返回列表开始匹配的索引。索引将从 0 开始。下面是我要执行的示例以进行说明:

subList [1,2,3] [4,4,1,2,3,5,6] 

结果应该是 2

我已尝试对其进行编码:

subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
        where select []     = []
              select (x:xs) = x

我收到“输入错误”,我无法弄清楚为什么我的语法不起作用。有什么建议吗?

【问题讨论】:

  • 我收到错误,但没有一个说“输入错误”。您确定您粘贴的代码准确无误吗?您是否尝试过使用 just 这段代码制作文件,以确保错误出现在这部分?

标签: list haskell recursion sublist


【解决方案1】:

我们先看一下函数签名。你想接受两个列表,它们的内容可以比较是否相等,并返回一个像这样的索引

subList :: Eq a => [a] -> [a] -> Int

所以现在我们对参数进行模式匹配。首先,当第二个列表为空时,我们无能为力,所以我们将返回 -1 作为错误条件

subList _ [] = -1

然后我们看递归步骤

subList as xxs@(x:xs)
  | all (uncurry (==)) $ zip as xxs = 0
  | otherwise                       = 1 + subList as xs

您应该熟悉我使用的保护语法,尽管您可能不熟悉 @ 语法。从本质上讲,这意味着xxs 只是我们使用(x:xs) 的子输入。

你可能不熟悉alluncurry,可能还有zip,所以让我详细说明一下。 zip 具有函数签名zip :: [a] -&gt; [b] -&gt; [(a,b)],因此它需要两个列表并将它们的元素配对(如果一个列表比另一个长,它只是砍掉多余的)。 uncurry 很奇怪,所以让我们看看(uncurry (==)),它的签名是(uncurry (==)) :: Eq a =&gt; (a, a) -&gt; Bool,它本质上是检查对中的第一个和第二个元素是否相等。最后,all 将遍历列表,查看每对的第一个和第二个是否相等,如果是则返回 true。

【讨论】:

  • 一周后alluncurryzip 也可能不那么明显(也许您应该使用zipWith 和一个lambda 来代替?) - 但很好的答案!跨度>
  • @CarstenKönig 好点,我会编辑它以更好地解释这一点
  • @randomusername 感谢您的解释,我对zip 有点熟悉,因为我一直在阅读“To Learn You A Haskell”一书。不过感谢您向我解释其他人。
  • @randomusername 我仍然对一件事有些困惑,当使用“@”语法时,我收到该符号的解析错误。这是为什么呢?
  • @ExecutionStyle21 可能是我把订单搞混了,我不记得应该是哪一个了。试试xxs@(x:xs)
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 2014-12-21
  • 2019-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-12
  • 2018-03-06
相关资源
最近更新 更多