Let's say I have a class that looks something like this:
class Foo(Prop1:Int, Prop2:Int, Prop3:Int)
{
..
}
And I wanted to create a function that gets the max of some arbitrary property from a list of Foo
s.
Like this:
def getMax(Foos:List[Foo], Property:??) = Foos.map(_.Property).sort(_ > _).head
If I called getMax(myFooList, Prop1)
, it would return the value of the highest Prop1
from this list of Foo
s.
My question is, how can I make this work? I guess I could create some kind of enum (the scala equivalent) for the Property
and do a match
and then run the map
on the appropriate property, but that seems like a lot of work - I'd have to extend my enum and the function each time Foo
is refactored.
Also, not as important, but is there a better way to grab the max value of a list then what I did?
The max() method is utilized to find the largest element of all the elements in the stated list. Return Type: It returns the largest of all the elements in the stated list.
Scala Int max() method with example The max() method is utilized to return the maximum value of the two specified int numbers. Return Type: It returns true the maximum value of the two specified int numbers.
How to get the max value in a list in R? First, use the unlist() function to convert the list into a vector, and then use the max() function to get the maximum value. The following are the arguments that you can give to the max() function in R. x – The vector for which you want to compute the max value.
You should use standard maxBy
method:
List(("a", 2), ("b", 3), ("c", 4)).maxBy(_._2)
=> (String, Int) = (c,4)
You can do this so simply using existing functionality that writing your own getMax is probably unnecessary:
scala> val fooList = List(Foo(1,2),Foo(2,2),Foo(3,2),Foo(4,2))
fooList: List[Foo] = List(Foo(1,2), Foo(2,2), Foo(3,2), Foo(4,2))
scala> fooList.map(_.p2).max
res12: Int = 2
scala> fooList.map(_.p1).max
res13: Int = 4
If you wanted to specify the property 'getter' elsewhere you could do it like this:
scala> def p1 = (f: Foo) => f.p1
p1: Foo => Int
scala> def p2 = (f: Foo) => f.p2
p2: Foo => Int
scala> fooList.map(p1).max
res14: Int = 4
scala> fooList.map(p2).max
res15: Int = 2
You can simply pass another function into getMax to instruct it how to map each Foo:
case class Foo(p1:Int, p2:Int)
def getMax(foos:List[Foo], mapper:Foo=>Int):Int = foos.map(mapper).foldLeft(Math.MIN_INT)((i,m)=>m.max(i))
val fooList = List(Foo(1,2),Foo(2,2),Foo(3,2),Foo(4,2))
getMax(fooList,_.p1)
//--> 4
The way I would do it is by passing to the getMax()
method a function that knows how to extract the required property out of your Foo
, i.e. something of type Foo => Int
.
The way I would do it therefore is as follows:
scala> case class Foo(p1: Int, p2: Int, p3: Int)
defined class Foo
scala> def getMax(foos: List[Foo], prop: Foo => Int) = foos.map(prop).sort(_ > _).head
getMax: (List[Foo],(Foo) => Int)Int
scala> val lst = List(Foo(1,2,3), Foo(2,3,4), Foo(3,4,5))
lst: List[Foo] = List(Foo(1,2,3), Foo(2,3,4), Foo(3,4,5))
scala> getMax(lst, _.p1)
res0: Int = 3
scala> getMax(lst, _.p2)
res1: Int = 4
scala> getMax(lst, _.p3)
res2: Int = 5
-- Flaviu Cipcigan
You can use objects inheriting from Product
. It will be simpler and more type safe if you know arity in advance:
def getMax(foos: List[Product2[Int,Int]], f: Product2[Int,Int] => Int) = foos.map{f} ....
Then, you are free to feed getMax
with anything like Tuple
, e.g.
class Foo(val prop1: Int, val prop2: Int) extends Tuple2[Int, Int](prop1, prop2)
// this will duplicate values in an object actually.
getMax((new Foo(1,2)), _._2)
or inherit right from Product
:
class Bar(val prop1: Int, val prop2: Int) extends Product2[Int, Int] {
def _1 = prop1
def _2 = prop2
}
val b = new Bar(2, 3)
getMax(List(b), _._2)
or simply use Scala's tuples:
getMax( (1,10) :: Nil, _._2)
getMax( List(1 -> 10), _._2)
// these are the same
Everything will become more complicated in case you do not know arity beforehand, because generic Product
will let you retrieve elements as Any
only (See Product.productElement(n: Int)
method) -- thus you are loosing type safety.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With