Scala:有没有一种优雅的方式来比较模式匹配中的值?

时间:2017-12-15 03:03:59

标签: scala pattern-matching

我正在尝试使用scala实现一个简单的二叉树。 我的树定义如下:

abstract class Tree[T <: Ordered[T]]
case class Node[T <: Ordered[T]](v:T, l:Tree[T], r:Tree[T]) extends Tree[T]
case class Leaf[T <: Ordered[T]](v:T) extends Tree[T]

我正在尝试实现一种方法来查找树中的最小值。方法实现如下:

def minInTree[T <: Ordered[T]](t: Tree[T]): T = t match {

    case Node(v, lft, rght) if minInTree(lft) > minInTree(rght) => {
        val mLft = minInTree(lft)
        val mRght = minInTree(rght)
        if (v > mRght)
           mRght
        else
           v
    }

    case Node(v, lft, rght) if minInTree(lft) <= minInTree(rght) => {
        val mLft = minInTree(lft)
        val mRght = minInTree(rght)
        if (v > mLft)
            mLft
        else
            v
    }
    case Leaf(lf) => lf
}

我发现minInTree(lft)minInTree(rght)被多次调用,我认为这是缓慢而丑陋的。比较使用多个if-else子句,我认为这也是丑陋的。

有没有优雅的方法来重组代码? 任何提示都表示赞赏。

3 个答案:

答案 0 :(得分:3)

如果您要使用Ordering类型类,则可以对您的值使用min()方法,这样可以使事情更加优雅。

abstract class Tree[T: Ordering]
case class Node[T: Ordering](v:T, l:Tree[T], r:Tree[T]) extends Tree[T]
case class Leaf[T: Ordering](v:T) extends Tree[T]

def minInTree[T](t: Tree[T])(implicit ev:Ordering[T]): T = t match {
  case Node(v, lft, rght) => ev.min(v, ev.min(minInTree(lft), minInTree(rght)))
  case Leaf(lf) => lf
}

导入一些方便的含义,min评估更清晰。

import Ordering.Implicits._
def minInTree[T: Ordering](t: Tree[T]): T = t match {
  case Node(v, lft, rght) => v min minInTree(lft) min minInTree(rght)
  case Leaf(lf) => lf
}

它还使基本比较操作可用。 (<>等。)

答案 1 :(得分:2)

我稍后会进行比较,我认为没有一种方法可以实现这一目标:

julia> x = ;date
ERROR: syntax: unexpected ;

julia> x = readstring(`date`)
"Thu Dec 14 21:33:48 PST 2017\n"
julia> x
"Thu Dec 14 21:33:48 PST 2017\n"

答案 2 :(得分:2)

正如jwvh所写,你可以使用Ordering来获得更清晰的代码。 另一种拥有更清晰代码的方法是使用继承代替模式匹配:

println("Welcome to the Scala worksheet")       //> Welcome to the Scala worksheet

sealed trait Tree[T] {
    def min(implicit ev : Ordering[T]) : T
}

case class Node[T](value : T, left : Tree[T], right : Tree[T]) extends Tree[T] {
    def min(implicit ev : Ordering[T]) : T = ev.min(value, ev.min(left.min(ev), right.min(ev)))
}

case class Leaf[T](value : T) extends Tree[T] {
    def min(implicit ev : Ordering[T]) : T = value
}

val tree = Node(17, Leaf(2), Node(4, Leaf(10), Leaf(8)))
                                              //> tree  : testTree#626615.Node#1020777[Int#918] = Node(17,Leaf(2),Node(4,Leaf(
                                              //| 10),Leaf(8)))
tree.min                                  //> res0: Int#918 = 2

我更喜欢在需要时为min方法添加Ordering类型类。 如果你还想要一个功能,那很简单:

def minTree[T](t : Tree[T])(implicit ev : Ordering[T]) = t.min
minTree(tree)                             //> res1: Int#918 = 2