Reputation: 7784
I wanted to write a function that, given a list of Int
s, returns a list in which every 2nd element has been doubled.
In Haskell the solution seems easy;
double = zipWith ($) (cycle [id,(*2)])
See here
Whats the most idiomatic way to do this in Scala?
Upvotes: 0
Views: 1250
Reputation: 41749
All the answers so far are hardwired to do what the poster specifically requested (i.e double every second element), but the Haskell implementation is a lot more flexible - the list of functions can easily be extended to do something different to, say, every first, second, third element.
Here's a Scala version that similarly uses a list of functions to cycle through
val fns = List[Int=>Int](identity, {x => x *2})
val xs = List(1,2,3,4)
def cycle[T](x:List[T]) = Iterator.continually(x).flatten.toIterable
val ys = xs zip cycle(fns)
ys map { case (v, f) => f(v)}
// List(1, 4, 3, 8)
Upvotes: 3
Reputation: 29
Not quite as concise Haskell, but it is pretty readable
(1 to 10).zipWithIndex.map { case (num, i) =>
if (i % 2 == 1) num * 2 else num
}
Upvotes: 2
Reputation: 3250
You can try this:
scala> val list = (1 to 10).toList
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> list.view.zipWithIndex.map(x => if(x._2 %2 != 0) 2*x._1 else x._1).toList
res6: List[Int] = List(1, 4, 3, 8, 5, 12, 7, 16, 9, 20)
Upvotes: 1
Reputation: 20285
Not the shortest but fun to write with recursion and pattern matching.
def double(xs: List[Int]) = {
@scala.annotation.tailrec
def doubleR(xs: List[Int], acc: List[Int]): List[Int] = xs match{
case Nil => acc
case h::Nil => (h +: acc)
case h::ht::t => doubleR(t, ht * 2 +: h +: acc)
}
doubleR(xs, List[Int]()).reverse
}
Test
scala> double(List(1,2,3,4,5))
res3: List[Int] = List(1, 4, 3, 8, 5)
Upvotes: 0
Reputation: 19497
One approach is to create a Stream
of ones and twos, then zip
your List
with this Stream
. This creates a List
of pairs: map
through this List
and multiply the tuple elements.
val oneTwoCycle: Stream[Int] = List(1, 2).toStream #::: oneTwoCycle
val data = (1 to 10).toList
val altDoubled = data.zip(oneTwoCycle).map(x => x._1 * x._2)
// List(1, 4, 3, 8, 5, 12, 7, 16, 9, 20)
Upvotes: 4
Reputation: 31192
Might not be the most idiomatic but one solution could be
scala> def double(list: List[Int]) = list.zipWithIndex.map{case (elem, index) => if(index==1) elem*2 else elem}
double: (list: List[Int])List[Int]
scala> double(List(1, 2, 3))
res7: List[Int] = List(1, 4, 3)
Or if you want every 2nd element within the same list to be doubled up,
scala> def double(list: List[Int]) = list.zipWithIndex.map{case (elem, index) => if((index+1)%2 == 0) elem*2 else elem}
double: (list: List[Int])List[Int]
scala> double(List(1, 2, 3, 4, 5, 6))
res2: List[Int] = List(1, 4, 3, 8, 5, 12)
Upvotes: 1