【问题标题】:Recursive program in Scala doesn't runScala中的递归程序不运行
【发布时间】:2014-07-12 02:36:17
【问题描述】:

我正在尝试使用递归在 Scala 中编写一个程序,以查看两个列表是否不相交。这是我第一次用 Scala 编写程序。

object Main {
    def member(x:Int,lst:List[Int]):Boolean= {
        if (lst == Nil)
            return false
        else
            if (x != lst.head)
                return member(x, lst.tail)
            else
                return true
    }

    def disjoint(s1:List[Int], s2:List[Int]):Boolean= {
        if (s1 == Nil)
            return true
        else
            if (member(s1.head,s2))
                return false
            else
                return disjoint(s1.tail, s2)
    }
     def main(args: Array[String]) {
        val lst1 = 2 :: (6 :: (1 :: Nil))
        val lst2 = 1 :: (3 :: (5 :: (7 :: (9 :: (11 :: Nil)))))
        val lst3 = disjoint(lst1, lst2)
     }
}

它编译但它不运行。我们将不胜感激所有帮助。

【问题讨论】:

  • 我得到 lst3: Boolean = false
  • 你可以省略这里所有的return字,顺便说一句

标签: list scala recursion


【解决方案1】:

这可能是您正在寻找的:

def areDisjoint[T](s1: Seq[T], s2: Seq[T]): Boolean =
  (s1.toSet & s2.toSet).isEmpty

val lst1 = List(2, 6, 1)
val lst1a = List(2, 6)
val lst2 = List(1, 3, 5, 7, 9, 11)
println(areDisjoint(lst1, lst2))
println(areDisjoint(lst1a, lst2))

=>

false
true

诀窍是使用Sets 上的& 运算符为您完成工作。 Set 使用哈希来有效地测试给定对象是否是成员。

【讨论】:

  • 我希望它适用于 lst.head 是 car 而 lst.tail 是 cdr 的 lisp 样式列表。
  • 确实如此。 Seq[T] 使其适用于任何类型的序列:List、Array 等等。
  • 我用 val lst1 =7 :: (6 :: (1 :: Nil)) 和 val lst2 = 1 :: (3 :: (5 :: (7 :: (9 :: (11 :: Nil))))) 但它不起作用。它仍然返回 false。
  • 这些列表不是不相交的。每个都包含一个1。顺便说一句,List(7, 6, 1) 与 7 :: (6 :: (1 :: Nil)) 相同。
  • @OshaMan 它应该返回 false
【解决方案2】:

如果您真的想使用递归只是为了了解如何在 Scala 中递归列表,方法如下:

def isMember(x: Int, l: List[Int]): Boolean =
  l match {
    case Nil => false
    case head :: tail => x == head || isMember(x, tail)
  }

def areDisjoint(l1: List[Int], l2: List[Int]): Boolean =
  l1 match {
    case Nil => true
    case head :: tail => !isMember(head, l2) && areDisjoint(tail, l2)
  }

match 执行"pattern-matching",它提供了一种从List 中提取头部和尾部的简单语法方法。请注意,这在实践中确实不是好的 Scala 代码,原因有以下三个:

  1. 它进行线性搜索并在 O(n^2) 时间内运行。 Set 版本的运行速度要快得多,至少在大型列表上是这样。

  2. List已经内置了.contains方法(见here),所以你真的不需要写isMember。

  3. 仅限于处理List[Int]。 Seq[T] 版本适用于任何类型的序列,包含任何类型的项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2013-01-07
    • 2014-10-29
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多