我有一些集合,它实现了def foreach(f: MyType => Unit): Unit
。
MyType
成员val value: Int
在正常情况下大于或等于零。
如何找到使用value
的最大foreach
元素的元素?
的 UPD: 的
def max: MyType
中应该有方法MyType
来实现这个逻辑。
答案 0 :(得分:5)
您可以实施scala.collection.Traversable
- 然后您可以使用方法maxBy
(以及Traversable
的所有其他方法):
import scala.collection.Traversable
case class MyType(value: Int)
class MyCollection {
def foreach(f: MyType => Unit): Unit = Seq(MyType(3), MyType(5), MyType(2)) foreach f
}
implicit class MyCollectionTraversable(c: MyCollection) extends Traversable[MyType] {
override def foreach[U](f: MyType => U): Unit = c.foreach{e => f(e); ()}
}
用法:
new MyCollection().maxBy{_.value}
// MyType = MyType(5)
您还可以像这样添加隐式Ordering[MyType]
:
import scala.math.Ordering
implicit val myTypeOrd = Ordering.by{ (_: MyType).value }
new MyCollection().max
// MyType = MyType(5)
您也可以手动添加自定义方法max
,但即使在这种情况下,MyCollectionTraversable
也会有用:
class MyCollectionTraversable(c: MyCollection) extends Traversable[MyType] {
override def foreach[U](f: MyType => U): Unit = c.foreach{e => f(e); ()}
}
implicit class MyCollectionHelper(val c: MyCollection) extends AnyVal {
def max: MyType = new MyCollectionTraversable(c).maxBy{_.value}
}
用法:
new MyCollection().max
// MyType = MyType(5)
答案 1 :(得分:3)
首先,为了解决这个问题:我认为foreach
不是解决这一特定问题的正确方法。由于它没有返回值,因此产生结果的唯一方法是副作用/可变性,这通常被视为Scala中要避免的事情。您应该查看reduce
和fold
方法,或其专门的min
,max
...版本。
如果您真的打算使用foreach
,则需要将一个闭包传递给foreach
,以更新在其范围之外维护的免费max
变量。
这不在袖口,但应该有效:
def max: MyType = {
var max = MyType(0)
foreach {t =>
if(t.value > max) max = t.value
}
max
}