Reputation: 13
Given an integer array nums:
-2,1,-3,4,6,-1,2,1,1,-5,4
I want to transform this array to another array:
-2,1,-3,10,-1,4,-5,4
Can I add a condition to the reduce function?
Something like that:
...
val nums = Array(-2,1,-3,4,6,-1,2,1,1,-5,4)
val reduced = nums.reduce((x, y) => {
if (x > 0 && y > 0){
x + y
}
})
...
Upvotes: 1
Views: 74
Reputation: 3206
A simple, non-tail recursive one:
def reducePositives(l: List[Int]): List[Int] = {
l.span(_ > 0) match {
case (Nil, Nil) => Nil
case (Nil, np :: rest) => np :: reducePositives(rest)
case (p, rest) => p.sum :: reducePositives(rest)
}
}
Upvotes: 0
Reputation: 1551
scala> val nums = Array(-2,1,-3,4,6,-1,2,1,1,-5,4)
nums: Array[Int] = Array(-2, 1, -3, 4, 6, -1, 2, 1, 1, -5, 4)
scala> nums.foldLeft(List[Int]()){
case (init :+ last, num) if last > 0 && num > 0 => init :+ (last + num)
case (res, num) => res :+ num
}
res0: List[Int] = List(-2, 1, -3, 10, -1, 4, -5, 4)
Or:
scala> def reduce(nums: Seq[Int]): Seq[Int] = nums match {
| case x1+:x2+:xs => if(x1>0 && x2>0) reduce((x1+x2)+:xs) else x1+:reduce(x2+:xs)
| case ns => ns
| }
def reduce(nums: Seq[Int]): Seq[Int]
scala> reduce(nums)
val res1: Seq[Int] = ArraySeq(-2, 1, -3, 10, -1, 4, -5, 4)
Upvotes: 1
Reputation: 1486
I am not sure if you can use reduce or another simple builtin-function to achieve your goal.
However, you can write a simple tail-recursive function that does what you want (it uses a list and pattern matching):
def sumPositives(arr: Array[Integer]): Array[Integer] = {
@scala.annotation.tailrec
def rec(list: List[Integer], acc: List[Integer]): List[Integer] = list match{
case x :: y :: rest if x >= 0 && y >= 0 => rec(x+y :: rest, acc)
case x :: y :: rest => rec(y :: rest, x :: acc)
case x :: Nil => (x :: acc).reverse
case Nil =>acc.reverse
}
rec(arr.toList, List()).toArray
}
Of course this could be simplified by using a list as input instead of an array, but in your question you specifically mentioned an array.
Upvotes: 0
Reputation: 4063
You can try next:
val result = Array(-2,1,-3,4,6,-1,2,1,1,-5,4).foldLeft(ListBuffer.empty[Int]) {
case (result, item) if item < 0 => result :+ item
case (result, item) if item > 0 => result.lastOption.filter(_ > 0).fold(result :+ item) { positiveSum =>
result.update(result.size -1, positiveSum + item)
result
}
}
println(result)
which will produce desired result: (-2, 1, -3, 10, -1, 4, -5, 4)
Hope this helps!
Upvotes: 0