This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Partial reduce on collection

5 replies
edmondo1984
Joined: 2011-09-14,
User offline. Last seen 28 weeks 3 days ago.
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
Viktor Klang
Joined: 2008-12-17,
User offline. Last seen 1 year 27 weeks ago.
Re: Partial reduce on collection


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
edmondo1984
Joined: 2011-09-14,
User offline. Last seen 28 weeks 3 days ago.
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>


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

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
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

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
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
>

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
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:
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

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland