Reputation: 2811
I have a case class:
case class Nums(num1: Int, num2: Int)
and a list as follows:
val listOfNums = List(Nums(1,1), Nums(2,2))
I want to return Nums(3,3)
which is the sum of all the relevant fields with each other. The way I achieved this was:
listOfNums.foldLeft(Nums(0,0))((acc,nums) => {
acc.copy(
num1 = acc.num1 + nums.num1,
num2 = acc.num2 + nums.num2
)
})
But this feels a bit clumsy, what would be the right way?
Upvotes: 0
Views: 643
Reputation: 22850
If you are open to using cats.
Then, you can simply define a Monoid
for nums
so you only need to write the boilerplate once, and then reuse it in multiple parts by using auxiliary functions like combineAll
or foldMonoid
import cats.kernel.Monoid
final case class Nums(num1: Int, num2: Int)
object Nums {
implicit final val NumsMonoid: Monoid[Nums] =
new Monoid[Nums] {
override final val empty: Nums =
Nums(num1 = 0, num2 = 0)
override def combine(n1: Nums, n2: Nums): Nums =
Nums(num1 = n1.num1 + n2.num1, num2 = n1.num2 + n2.num2)
}
}
Which then can be used like:
import cats.syntax.all._
val listOfNums = List(Nums(1,1), Nums(2,2))
val result = listOfNums.combineAll
// result: Nums = Nums(3, 3)
You can see the code running here.
Upvotes: 1
Reputation: 8529
Actually what you are looking for is Reduce
, and not fold
. You can try:
listOfNums.reduce((num1, num2) => Nums(num1.num1 + num2.num1, num1.num2 + num2.num2))
If you do want to use fold, you don't have to copy, you can just create a new Nums
:
listOfNums.foldLeft(Nums(0,0))((acc,nums) => {
Nums(
num1 = acc.num1 + nums.num1,
num2 = acc.num2 + nums.num2
)
})
You can further read about difference between foldLeft and reduceLeft in Scala.
Code run can be found at Scastie.
As @Thilo mentioned in the comment, you can add a +
to Nums
:
case class Nums(num1: Int, num2: Int) {
def +(that: Nums): Nums = {
Nums(num1 + that.num1, num2 + that.num2)
}
}
And then the fold
and reduce
usage become really obviuos:
listOfNums.reduce(_ + _)
listOfNums.foldLeft(Nums(0,0))(_ + _)
Code run for that in another Scastie
Upvotes: 4