在Scala中使用foreach查找最大值

时间:2014-02-08 09:27:16

标签: scala foreach

我有一些集合,它实现了def foreach(f: MyType => Unit): Unit

MyType成员val value: Int在正常情况下大于或等于零。

如何找到使用value的最大foreach元素的元素?

UPD:

def max: MyType中应该有方法MyType来实现这个逻辑。

2 个答案:

答案 0 :(得分:5)

Traversable的

您可以实施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中要避免的事情。您应该查看reducefold方法,或其专门的minmax ...版本。

如果您真的打算使用foreach,则需要将一个闭包传递给foreach,以更新在其范围之外维护的免费max变量。

这不在袖口,但应该有效:

def max: MyType = {
    var max = MyType(0)
    foreach {t =>
        if(t.value > max) max = t.value
    }
    max
}