write this more concisely.

59 visualizzazioni
Passa al primo messaggio da leggere

Jim Newton

da leggere,
26 ago 2016, 08:30:1826/08/16
a scala-user
Is there a way to write this more concisely?

val mass:Float = bodies.foldLeft(0f)((x:Float,b:Body)=>x+b.mass)
val massX:Float = bodies.foldLeft(0f)((mx:Float,b:Body)=>(mx + b.x*b.mass)) / mass
val massY:Float = bodies.foldLeft(0f)((my:Float,b:Body)=>(my + b.y*b.mass)) / mass


The (Coursera) exercise I'm working suggests the following.  Can it be done with a single fold?

 val (mass, massX, massY) = (??? : Float, ??? : Float, ??? : Float)


Rodrigo Cano

da leggere,
26 ago 2016, 09:16:4126/08/16
a Jim Newton, scala-user
Yes it can, by means of pattern matching.
Like what you just wrote, if you do

val (a, b, c) = (1.0, 2.0, 3.0)

each variable gets assigned one of those numbers, it performs a pattern match with the tuple, depending on what pattern you do, you may even get MatchError as in:

val someOption: Option[Int] = None
val Some(someInt) = someOption // this compiles fine but the pattern match will throw a MatchError in runtime

Were someOption to be an actual Some[Int] in that case, and then you would have a variable named someInt with the value extracted from it.

So the final answer to your question would be, yes you can do it one fold, but you have to work it out so that that fold returns a Tuple3 with each component.

Cheers.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jim Newton

da leggere,
26 ago 2016, 09:41:4026/08/16
a scala-user, jimka...@gmail.com
I think it is even more difficult because massX and massY depend on mass.

Alexey Shuksto

da leggere,
27 ago 2016, 04:06:5227/08/16
a scala-user, jimka...@gmail.com
I need final value of `mass` to compute `massX` and `massY`, so doing it in one fold seems impossible to me.

However, you can do that in two folds:

val (mass, mxy) = ((0F, List.empty[(Float, Float)]) /: bodies) {
  case ((m, ms), body) => (m + body.mass, (body.x * body.mass, body.y * body.mass) :: ms)
}
val (massY, massX) = ((0F, 0F) /: mxy) {
  case ((mx, my), (mx0, my0)) => ((mx + mx0) / mass, (my + my0) / mass)
}

пятница, 26 августа 2016 г., 16:41:40 UTC+3 пользователь Jim Newton написал:

Gabriel Claramunt

da leggere,
27 ago 2016, 09:23:2027/08/16
a Alexey Shuksto, scala-user, jimka...@gmail.com
I'm pretty sure it can be done in one pass, you need to accumulate and divide by mass at the end. 
The technique is called "tupling" and here is an example of how to use it to calculate the average of a list

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Gabriel Claramunt

Rex Kerr

da leggere,
27 ago 2016, 11:11:1927/08/16
a Alexey Shuksto, scala-user, Jim Newton
Why fold again?  If you want to divide by mass, you can divide the sum (as you showed originally).

  --Rex


--

Alexey Shuksto

da leggere,
27 ago 2016, 11:16:1227/08/16
a scala-user, ale...@shuksto.name, jimka...@gmail.com
Ah, I see now -- I thought that we need to divide (acc + b.x * b.mass) by mass on every step of mx/my folding.
But in original computation we divide total sums.

Then yes, absolutely doable in one fold.

суббота, 27 августа 2016 г., 18:11:19 UTC+3 пользователь Rex Kerr написал:
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
Rispondi a tutti
Rispondi all'autore
Inoltra
0 nuovi messaggi