NightWolf
NightWolf

Reputation: 7784

Scala - Double every 2nd element in list

I wanted to write a function that, given a list of Ints, 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

Answers (6)

The Archetypal Paul
The Archetypal Paul

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

user1237032
user1237032

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

Mahesh Chand
Mahesh Chand

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

Brian
Brian

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

Jeffrey Chung
Jeffrey Chung

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

prayagupadhyay
prayagupadhyay

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

Related Questions