简体   繁体   中英

Find maximum using foreach in Scala

I have some collection, that implements def foreach(f: MyType => Unit): Unit .

MyType has member val value: Int that is greater or equals to zero in normal case.

How coud i find element with maximum value using foreach ?

UPD:

There should be method def max: MyType within MyType implementing this logic.

Traversable

You could implement scala.collection.Traversable - then you could use method maxBy (and all other methods of 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); ()}
}

Usage:

new MyCollection().maxBy{_.value}
// MyType = MyType(5)

You could also add implicit Ordering[MyType] like this:

import scala.math.Ordering
implicit val myTypeOrd = Ordering.by{ (_: MyType).value }

new MyCollection().max
// MyType = MyType(5)

Custom method

You could also add your custom method max manually but even in this case MyCollectionTraversable will be useful:

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}
}

Usage:

new MyCollection().max
// MyType = MyType(5)

First, to get this out of the way: I feel that foreach is not the right method for this particular problem. Since it doesn't have a return value, the only way for it to yield a result is by side effects / mutability, which is generally seen as something to avoid in Scala. You should probably look into the reduce and fold methods, or their specialised min , max ... versions.

If you're really intent on using foreach , you need to pass a closure to foreach that updates a free max variable maintained outside of its scope.

This is off the cuff but should work:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM