1

I followed the Xtend tutorial and the Movies example. At the end of this tutorial, you can find this question:

    @Test def void sumOfVotesOfTop2() {
      val long sum = movies.sortBy[ -rating ].take(2).map[ numberOfVotes ].reduce[ a, b | a + b ]
      assertEquals(47_229L, sum)
    }

First the movies are sorted by rating, then we take the best two. Next the list of movies is turned into a list of their numberOfVotes using the map function. Now we have a List which can be reduced to a single Long by adding the values.

You could also use reduce instead of map and reduce. Do you know how?

My question is: What is the best answer for the last question ?

I found a way to compute the same "sum" value without using map() extension method, but it seems awful for me. Here is my solution:

assertEquals(47229, this.movies.sortBy[ -rating ].take(2).reduce[m1, m2 | new Movie('', 0, 0.0, m1.numberOfVotes + m2.numberOfVotes,null)].numberOfVotes)

Is there a better (and cleaner) way to do that ?

Antwane
  • 20,760
  • 7
  • 51
  • 84

1 Answers1

2

You could use fold(R seed, (R,T)=>R function) instead of reduce((T,T)=>T):

assertEquals(47229, 
  movies
    .sortBy[rating]
    .reverseView
    .take(2)
    .fold(0L) [ result, movie | result + movie.numberOfVotes ])

Please note that map((T)=>R) does not perform any eager computation but is evaluated on demand, so performance should not matter for a solution that uses the map function. Nevertheless, fold is quite handy if you need to accumulate a result for a set of values where the result type different from the element type.

Sebastian Zarnekow
  • 6,609
  • 20
  • 23
  • 1
    I agree, but Xtend in tutorial, Question 3 said it is possible to replace a `map[ numberOfVotes ].reduce[ a, b | a + b ]` by a simple `reduce` call, this is what I don't understand. Is it really possible to have a nice way to do that ? – Antwane Mar 21 '13 at 10:37