Sometimes questions like these appear in a mutable context and just get carried over to an immutable one without really deciding whether it’s the kind of thing one would do.
If Scala had a built-in group-by-equivalence-class method, which it doesn’t, then it would be a simple matter of expressing that even values are equivalent to each other and odd values aren’t equivalent to anything. (e.g. (a % 2) | (b %2) == 0
would be the equivalence criterion).
You can fake it with scan
.
val ecs = xs.scan(0){ (c, x) => if x % 2 == 0 then (c + 1) & ~1 else (c + 1) | 1 }.drop(1)
(The odd bit math is there to make sure odd values have odd equivalence class numbers which keep increasing, while even values advance to an even equivalence class number and then stay there.)
Now we can use groupBy
to actually gather the elements.
val sums = (ecs zip xs).groupBy(_._1).mapValues(_.map(_._2).sum).toSeq.sortBy(_._1).map(_._2)
So, overall, it’s kind of a two-liner. Not a very pretty two-liner, granted.
But it really ought to be
xs.chunkWith((a, b) => ((a % 2) | (b % 2)) == 0).map(_.sum)
Given that the scan/groupBy version is pretty messy, it’s worth considering
var sum = 0
val ysb = Seq.newBuilder[Int]
for (a, b) <- xs.zipAll(xs.drop(1), 0, 1) do
if a % 2 == 0 then
sum += a
if b % 2 != 0 then ysb += sum
else
sum = 0
ysb += a
val ys = ysb.result
(If you had an indexable sequence, you’d probably index instead of using the zipAll
trick.)