【问题标题】:Confused about merge sort implementation对合并排序实现感到困惑
【发布时间】:2012-10-26 10:08:43
【问题描述】:

这一行发生了什么,x 被连接到 xs1,但 xxs1 没有在任何地方定义?

case (x :: xs1, y :: ys1) =>

同样在这里,下面的xy 有什么价值?合并是否作为案例类的一部分被递归调用?

if( x < y) x :: merge(xs1 , ys)

这是完整的 Scala 代码:

object mergesort {

    def msort(xs: List[Int]): List[Int] = {
        val n = xs.length / 2
        if(n == 0) xs
        else {
            def merge(xs: List[Int], ys: List[Int]): List[Int] = (xs , ys) match {
            case (Nil, ys) => ys
            case (xs, Nil) => xs
            case (x :: xs1, y :: ys1) =>
                if( x < y) x :: merge(xs1 , ys)
                else y :: merge(xs, ys1)
            }


        val (fst, snd) = xs splitAt n
        merge(msort(fst), msort(snd))
        }
    }                                         //> msort: (xs: List[Int])List[Int]

    val nums = List(2, -4, 5, 7, 1)           //> nums  : List[Int] = List(2, -4, 5, 7, 1)
    msort(nums)                               //> res0: List[Int] = List(-4, 1, 2, 5, 7)

}

【问题讨论】:

标签: scala


【解决方案1】:

case (x :: xs1, y :: ys1) =>  

:: 是模式匹配中的语法糖,用于将list 解构为headtail

列表xs 被解构为head x 和tail xs

在模式匹配中,:: 解构一个列表,与正常情况下的实际操作完全相反,construct 一个列表。

阅读The Point of Pattern Matching in Scala中的De-Constructing objects

【讨论】:

    【解决方案2】:

    这个

    (xs , ys) match {
         ...     
        case (x :: xs1, y :: ys1) 
    

    是一个模式匹配,它在与断言序列匹配相同的语句中声明变量xxs1 等。

    上面的代码检查 xs 是否可以分解成一个带有头 x 和尾 xs1 的序列,如果是这样,则使头/尾可用于这两个变量中的后续代码块。

    回答你的第二个问题(因为没有其他人有!),是的,merge 函数(在外部函数中声明)被递归调用。

    【讨论】:

      【解决方案3】:

      以下是 scala 如何允许您在列表上进行模式匹配的示例:

      scala> List(1,2,3)
      res0: List[Int] = List(1, 2, 3)
      
      scala> res0 match {
           | case h :: t => "more than two elements, " + h + " is the first"
           | case _ => "less than two elements"
           | }
      res1: java.lang.String = more than two elements, 1 is the first
      

      请注意,case 左侧的 :: 在其头部 (1) 和尾部(列表的其余部分 2, 3)中分解列表并将值绑定到 ht,仅在第一个 case 内创建和限定范围。

      分解元组的方法如下:

      scala> val tp = ("a", 1)
      tp: (java.lang.String, Int) = (a,1)
      
      scala> tp match {
           | case (a, b) => a + " is a string, " + b + " is a number"
           | case _ => "something missing"
           | }
      res2: java.lang.String = a is a string, 1 is a number
      

      在您问题的代码中,您在列表元组(xs , ys) 上混合了事物和模式匹配。

      case (x :: xs1, y :: ys1) 既在其两个列表中分解元组,又在其各自的头部和尾部分解其两个列表。

      【讨论】:

        【解决方案4】:

        在 scala 中使用 match-case 关键字来执行模式匹配,这是一种使用案例类和提取器等多种机制来匹配/分解对象的方法。 Google for scala 模式匹配,你会找到你需要的答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-25
          • 1970-01-01
          • 2018-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-25
          • 2016-10-10
          相关资源
          最近更新 更多