- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers

# Partial reduce on collection

Thu, 2012-01-12, 17:33

Dear all,given two arrays, one of boolean and one of double with the same size, I need to produce a third array of doubles containing partial sums of the double array. I zipped the two arrays, and now I need , when an item has its boolean = false to sum it to the following until one is found with flag =true

Example:

True 0.1true 0.2false 0.3false 0.4true 0.5

Result =>0.10.20.5+0.4+0.3=1.2

Which is the best way to do this in Scala

Best RegardsEdmondo

Example:

True 0.1true 0.2false 0.3false 0.4true 0.5

Result =>0.10.20.5+0.4+0.3=1.2

Which is the best way to do this in Scala

Best RegardsEdmondo

Thu, 2012-01-12, 17:51

#2
Re: Partial reduce on collection

Something better than this crap

lazy val groupedItems = { val grouped= Array.ofDim(activeCount)[Double]; var i = 0; var k = 0; var sum=0d; while(i<original.size){ sum+= original (i); if(flags(i)){ output(k)=sum; k+=1; sum=0; } } grouped; }

2012/1/12 √iktor Ҡlang <viktor [dot] klang [at] gmail [dot] com>

lazy val groupedItems = { val grouped= Array.ofDim(activeCount)[Double]; var i = 0; var k = 0; var sum=0d; while(i<original.size){ sum+= original (i); if(flags(i)){ output(k)=sum; k+=1; sum=0; } } grouped; }

2012/1/12 √iktor Ҡlang <viktor [dot] klang [at] gmail [dot] com>

On Thu, Jan 12, 2012 at 5:33 PM, Edmondo Porcu <edmondo [dot] porcu [at] gmail [dot] com> wrote:

Dear all,given two arrays, one of boolean and one of double with the same size, I need to produce a third array of doubles containing partial sums of the double array. I zipped the two arrays, and now I need , when an item has its boolean = false to sum it to the following until one is found with flag =true

Example:

True 0.1true 0.2false 0.3false 0.4true 0.5

Result =>0.10.20.5+0.4+0.3=1.2

Which is the best way to do this in Scala

Best in what respect?

Best RegardsEdmondo

--

Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang

Thu, 2012-01-12, 18:01

#3
Re: Partial reduce on collection

val x = List(true, true, false, false, true )

val y = List( 0.1, 0.2, 0.3, 0.4, 0.5 )

val filter = x.zip(true :: x.init).map({ case (pred, succ) => !pred || !succ }) // --> false, false, true, true, true

y.zip(filter).collect({ case (x, true) => x }).sum

On 12 Jan 2012, at 16:33, Edmondo Porcu wrote:

> Dear all,

> given two arrays, one of boolean and one of double with the same size, I need to produce a third array of doubles containing partial sums of the double array.

> I zipped the two arrays, and now I need , when an item has its boolean = false to sum it to the following until one is found with flag =true

>

> Example:

>

> True 0.1

> true 0.2

> false 0.3

> false 0.4

> true 0.5

>

> Result =>

> 0.1

> 0.2

> 0.5+0.4+0.3=1.2

>

> Which is the best way to do this in Scala

>

> Best Regards

> Edmondo

Thu, 2012-01-12, 18:21

#4
Re: Partial reduce on collection

(

actually you can just do

val filter = x.zip(true :: x).map({ case (pred, succ) => !pred || !succ })

because the zipped result will be as short as the shorter of the two inputs, and i guess `init` is an expensive operation for large `List`s.

)

On 12 Jan 2012, at 16:48, Sciss wrote:

> val x = List(true, true, false, false, true )

> val y = List( 0.1, 0.2, 0.3, 0.4, 0.5 )

>

> val filter = x.zip(true :: x.init).map({ case (pred, succ) => !pred || !succ }) // --> false, false, true, true, true

> y.zip(filter).collect({ case (x, true) => x }).sum

>

> On 12 Jan 2012, at 16:33, Edmondo Porcu wrote:

>

>> Dear all,

>> given two arrays, one of boolean and one of double with the same size, I need to produce a third array of doubles containing partial sums of the double array.

>> I zipped the two arrays, and now I need , when an item has its boolean = false to sum it to the following until one is found with flag =true

>>

>> Example:

>>

>> True 0.1

>> true 0.2

>> false 0.3

>> false 0.4

>> true 0.5

>>

>> Result =>

>> 0.1

>> 0.2

>> 0.5+0.4+0.3=1.2

>>

>> Which is the best way to do this in Scala

>>

>> Best Regards

>> Edmondo

>

Thu, 2012-01-12, 18:51

#5
Re: Partial reduce on collection

Do you want this to be fast to run or fast to code?

Let's say we have

val ns = Array(0.1, 0.2, 0.3, 0.4, 0.5)

val tf = Array(true, true, false, false, true)

If you want it to be fast to run, it's a bit of work, as you've already shown:

def chopsum(ns: Array[Double], tf: Array[Boolean]) = {

var i = 0

var n = 0

val L = math.min(ns.length, tf.length)

while (i < L) {

if (tf(i)) n += 1

i += 1

}

if (!tf(L-1)) n += 1

val result = new Array[Double](n)

var i = 0

var n = 0

while (i < L) {

result(n) += ns(i)

if (tf(i)) n += 1

i += 1

}

result

If you want your code to be compact, you can, for instance,

def chopsum(xs: Seq[(Double, Boolean)], answer: Vector[Double] = Vector()): Vector[Double] = {

if (xs.isEmpty) answer

else {

val (pre, post) = xs.span(! _._2)

chopsum(post.drop(1), answer :+ (pre ++ post.take(1)).map(_._1).sum)

}

}

chopsum(ns zip ts)

This is about the best you can do, given that Scala doesn't have a chop-into-groups method. I have one on StackOverflow at http://stackoverflow.com/questions/5410846 as my example of adding a method to collections. Using that (the version that works with arrays), one could simply

(ns zip tf).groupedWhile((x,_) => !x._2).map(_.map(_._1).sum)

which illustrates why such a method was sufficiently heavily asked-for that I used it as my example.

--Rex

On Thu, Jan 12, 2012 at 11:33 AM, Edmondo Porcu <edmondo [dot] porcu [at] gmail [dot] com> wrote:

Let's say we have

val ns = Array(0.1, 0.2, 0.3, 0.4, 0.5)

val tf = Array(true, true, false, false, true)

If you want it to be fast to run, it's a bit of work, as you've already shown:

def chopsum(ns: Array[Double], tf: Array[Boolean]) = {

var i = 0

var n = 0

val L = math.min(ns.length, tf.length)

while (i < L) {

if (tf(i)) n += 1

i += 1

}

if (!tf(L-1)) n += 1

val result = new Array[Double](n)

var i = 0

var n = 0

while (i < L) {

result(n) += ns(i)

if (tf(i)) n += 1

i += 1

}

result

If you want your code to be compact, you can, for instance,

def chopsum(xs: Seq[(Double, Boolean)], answer: Vector[Double] = Vector()): Vector[Double] = {

if (xs.isEmpty) answer

else {

val (pre, post) = xs.span(! _._2)

chopsum(post.drop(1), answer :+ (pre ++ post.take(1)).map(_._1).sum)

}

}

chopsum(ns zip ts)

This is about the best you can do, given that Scala doesn't have a chop-into-groups method. I have one on StackOverflow at http://stackoverflow.com/questions/5410846 as my example of adding a method to collections. Using that (the version that works with arrays), one could simply

(ns zip tf).groupedWhile((x,_) => !x._2).map(_.map(_._1).sum)

which illustrates why such a method was sufficiently heavily asked-for that I used it as my example.

--Rex

On Thu, Jan 12, 2012 at 11:33 AM, Edmondo Porcu <edmondo [dot] porcu [at] gmail [dot] com> wrote:

Example:

True 0.1true 0.2false 0.3false 0.4true 0.5

Result =>0.10.20.5+0.4+0.3=1.2

Which is the best way to do this in Scala

Best RegardsEdmondo

On Thu, Jan 12, 2012 at 5:33 PM, Edmondo Porcu <edmondo [dot] porcu [at] gmail [dot] com> wrote:

Best in what respect?

--

Viktor Klang

Akka Tech LeadTypesafe - The software stack for applications that scale

Twitter: @viktorklang