Scala - 将列表中的每个第二个元素加倍

问题描述:

我想写一个函数,给定一个列表Int s,返回一个列表,其中每个第二个元素已经加倍。Scala - 将列表中的每个第二个元素加倍

在Haskell中,解决方案看起来很简单;

double = zipWith ($) (cycle [id,(*2)])here

请告诉我最习惯的方式在Scala中做到这一点?

+1

'list.zipWithIndex.map(X => x._1 *(1+(1&x._2)))' – jwvh

可能不是最地道,但一个解决办法是

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) 

或者,如果你想在同一个列表中的每个第二个元素被成倍上涨,

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) 
+1

'list.zipWithIndex.map {case(elem,1)=> elem * 2 case(elem,_)=> elem}'' – yesemsanthoshkumar

一种方法是创建Stream的一个和两个,然后zip您的List与此Stream。这会创建List对:map到此List并乘以元组元素。

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) 

不是用递归和模式匹配写的最短但有趣的。

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 
    } 

测试

scala> double(List(1,2,3,4,5)) 
res3: List[Int] = List(1, 4, 3, 8, 5) 

你可以试试这个:

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) 

不太简明哈斯克尔,但它是相当可读

(1 to 10).zipWithIndex.map { case (num, i) => 
    if (i % 2 == 1) num * 2 else num 
} 

所有答案为止硬连线做海报特别要求的东西(即每第二个元素为双精度值),但Haskell的实现更加灵活 - 函数列表可以很容易地扩展为对每个第一,第二,第三个元素做不同的事情。

下面是同样采用的功能,以循环的列表通过Scala的版本

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)