1

我有一种方法可以将不同类型的元组添加到列表中,其中第一个元组元素始终是 Int。我需要进行“大于”比较,但这在 Any 类型上是不允许的。有人可以告诉我如何在下面达到预期的效果吗?

谢谢德斯

private def add(list: List[Product], item: Product): List[Product] = {
  if(list.isEmpty || list.head.productElement(0) > item.productElement(0)) item :: list
  else add(list.tail, item)
}
4

2 回答 2

1

如果你不能接受ziggystar的建议,因为它Producer具有可变的数量,你可以通过重构来达到预期的效果,避免使用复杂且可能不太可读的方法。例如:

case class Item(i: Int, item: Product)

def add(list: List[Item], item: Item): List[Item] = {
  if (list.isEmpty || list.head.i > item.i) item :: list
  else add(list.tail, item)
}

使用时,它看起来像这样:

add(Nil, Item(1, (1, "b"))) // List(Item(1,(1,b)))
add(List(Item(1, (1, "a"))), Item(2, (1, "b"))) // List(Item(2,(1,b)))
add(List(Item(2, (1, "a"))), Item(1, (1, "b"))) // List(Item(1,(1,b)), Item(2,(1,a))
于 2013-03-06T16:14:12.293 回答
0

如果您愿意诉诸反射,您可以混合使用名义类型和结构类型:

import scala.language.reflectiveCalls

// A structural type exploiting the fact that all tuples have a _1 field
type IntComponent = { val _1: Int }

def add(list: List[Product with IntComponent], item: Product with IntComponent): List[Product with IntComponent] = {
  if(list.isEmpty || list.head._1 > item._1) item :: list
  else add(list.tail, item)
}

这种组合Product with IntComponent并不是绝对必要的,IntComponent就足够了。但是,这种组合为您提供了更多的安全性,并且它允许您使用Productif 需要时声明的字段和方法。

这为您提供了相当多的静态类型安全性:

add(Nil, (1, "foo", null)) // ok

add(Nil, ("foo", 0)) // error
  // error: type mismatch;
  //    found   : String("foo")
  //    required: Int

add(List[Product with IntComponent](Tuple1(1), Tuple2(-1, true)), (0, "yes"))
  // Explicit type annotation required, error otherwise
  //     found   : List[Product with Serializable]
  //     required: List[Product with this.IntComponent]

这种方法的明显弱点是,您可以潜入任何 a 的对象,Product with IntComponent例如

case class FakeTupleA(_1: Int)

add(Nil, FakeTupleA(99)) // ok

如果没有Product要求,以下内容也可以工作:

add(Nil, new FakeTupleB(99))
  // error: type mismatch;
    // found   : this.FakeTupleB
    // required: Product with this.IntComponent
于 2013-03-06T14:58:58.017 回答