【问题标题】:Scala order implicit conversions?Scala订单隐式转换?
【发布时间】:2017-05-24 09:07:58
【问题描述】:

我在隐含的 scala 顺序中有一些问题,有人可以帮助我吗?

下面是一些类的定义,我想做的是通过它的“流行度”来比较Leaf和Node。

class Tree

case class EmptyTree() extends Tree

case class Leaf(label: String, popularity: Double) extends Tree

case class Node(popularity: Double, left: Tree, right: Tree) extends Tree

例如:

val a = Leaf("a",10)
val b = Leaf("b",20)
val c = Node(30,a,b)

如果我们想通过 a 和 b 的受欢迎程度来比较它,通过添加隐式转换很容易做到,就像这样:

implicit val leavesOrder = new Ordering[Leaf] {
override def compare(x: Leaf, y: Leaf) = 
  implicitly[Ordering[Double]].compare(x.popularity, y.popularity)
}

但是如果我想通过 a 和 c 的受欢迎程度来比较它,我对此感到困惑并且不知道如何添加隐式转换?

有人可以帮我吗?

【问题讨论】:

  • 你的问题有点含糊。您的标题谈到了隐式顺序,但您似乎正在寻找隐式转换?
  • 你可以创建一个new Ordering[Tree]
  • 对不起,我会修改瓷砖。@YuvalItzchakov
  • 你能详细描述一下吗?@LukaJacobowitz
  • 当然,请看下面我的回答:)

标签: scala implicit


【解决方案1】:

如果要比较 Leafs 和 Nodes,可以为 Tree 创建隐式 Ordering

这里有一些(不完整的)代码,关于如何做到这一点:

implicit val treeOrder = new Ordering[Tree] {
  override def compare(x: Tree, y: Tree) = (x,y) match {
    case (Leaf(_,xP), Leaf(_,yP)) => xP compare yP
    case (Node(xP,_,_), Leaf(_,yP)) => xP compare yP
    case (Node(xP,_,_), Node(yP,_,_)) => xP compare yP
    case (EmptyTree(), _) => -1
    /* Add the rest of the cases here */
  }
}

Tree 更改为sealed trait 的奖励积分,以便编译器可以在您的模式匹配不完整时告诉您:)

【讨论】:

  • 嗨 Luka,提前感谢,当我尝试在我的示例中测试您的代码时,出现以下消息,“没有为 Leaf 定义隐式排序”。下面是我的例子: val a = Leaf("a", 3) val b = Leaf("b", 5) val e = Leaf("e", 6) val c = Node( 10, a, b) val d = Node(11, c, a) val s = Array(e,a, b).sorted
  • 嗯,这对我有用,你能告诉我更多你的代码吗?
  • 有效,初始化Array时应添加Tree类型。
  • 是的,类型需要被推断为树,你可以通过使用类型注释来强制,或者当你有一个不同类型的层次结构的数组时编译器会为你推断它。 :)
【解决方案2】:

我会做这样的事情。将您的 Tree 类更改为 sealed trait 这意味着模式匹配是详尽的,因此编译器可以告诉您是否缺少某些内容。然后,您需要匹配 Tree 可以是的每种类型。并非所有人都有人气。

sealed trait Tree

case object EmptyTree extends Tree

case class Leaf(label: String, popularity: Double) extends Tree

case class Node(popularity: Double, left: Tree, right: Tree) extends Tree

implicit val treeOrdering = new Ordering[Tree] {

  private val doubleOrdering = implicitly[Ordering[Double]]

  def compare(a: Tree, b: Tree): Int = {
    (a, b) match {
      case (Node(p1, _, _), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
      case (Leaf(_, p1), Node(p2, _, _)) => doubleOrdering.compare(p1, p2)
      case (Node(p1, _, _), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
      case (Leaf(_, p1), Leaf(_, p2)) => doubleOrdering.compare(p1, p2)
      case (EmptyTree, _) => -1
      case (_, EmptyTree) => 1
    }
  }

}

【讨论】:

  • 谢谢,我正在尝试你的方法。
  • 您好,在此先感谢您,当我尝试在我的示例中测试您的代码时,会出现以下消息,“没有为 Leaf 定义隐式排序”。下面是我的例子: val a = Leaf("a", 3) val b = Leaf("b", 5) val e = Leaf("e", 6) val c = Node( 10, a, b) val d = Node(11, c, a) val s = Array(e,a, b).sorted
  • val treeOrdering = ...更改为implicit val treeOrdering = ...
  • 你需要 Array[Tree](e,a, b).sorted gist.github.com/stephennancekivell/…
  • 那行得通,但是为什么 val s:Array[Tree] = Array(e, a, b).sorted 不起作用?
猜你喜欢
  • 1970-01-01
  • 2012-04-15
  • 2018-09-16
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多