【问题标题】:Find the subset of a list查找列表的子集
【发布时间】:2021-11-13 03:44:57
【问题描述】:

我正在用 SML 编写一个函数来查找两个整数集的子集。例如,subset([1,5],[1,3,5]) 应该返回 true。我在编写这个函数时遇到了一点麻烦。我的问题是我应该如何递归地编写这个。 这是我的功能:

fun subset(lst1,lst2) = true
  |  subset(a::;lst1,lst2) =
       if member(a,lst2) then subset(lst1,lst2)
       else false;

【问题讨论】:

  • 正如我在回答您上一个问题时所建议的那样,请参阅this answer 关于您直接从中获取代码的递归。请向我们展示递归解决此问题的尝试,我们可以回答有关特定错误的问题。
  • 你在正确的轨道上,但如果ls1 的所有元素都是ls2 的成员,ls1ls2 的子集,而不是ls1 本身。想想lst1 是空集的情况,以及不是空集的情况(即至少有一个成员)。
  • 另外,顺序重要吗?
  • 我编辑了我的代码以使用递归。不过,我遇到了一些错误。此外,顺序无关紧要。

标签: sml


【解决方案1】:

好的,在 cmets 之后,如果任何一个列表是另一个列表的子集,您似乎想要一个为真的谓词。

这很难一次完成;同时递归两个列表会很快变得复杂。

相反,当且仅当lst1lst2 的子集时,让我们修复您的代码并使其成为真的。

那么我们就可以用它来实现想要的功能了:

fun either_subset(xs, ys) = subset(xs, ys) orelse subset(ys, xs)

您的第一个模式匹配所有对,并且模式匹配按照它们写入的顺序进行尝试,因此结果始终为true
您可以通过两种方式解决此问题;要么使第一种情况更具体,并且只匹配空列表,

fun subset([],lst2) = true

或重新排列子句,使第一个 case 匹配任何非空列表,

fun subset(a::lst1,lst2) =
       if member(a,lst2) then subset(lst1,lst2)
       else false
  | subset(lst1,lst2) = true

您也可以简化这一点 - if e1 then e2 else false 等价于 e1 andalso e2,当您不使用模式的名称时,您可以使用通配符模式 _

fun subset(x::xs, ys) = member(x, ys) andalso subset(xs, ys)
  | subset _ = true

fun subset ([], _) = true
  | subset (x::xs, ys) = member(x, ys) andalso subset(xs, ys)

【讨论】:

  • 我知道这是一个主观的事情,但我总是感觉正确首先表达递归的“基本”案例。
猜你喜欢
  • 2015-03-06
  • 2021-03-14
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
相关资源
最近更新 更多