在Scala中通过奇怪的集合成员进行迭代

时间:2012-10-08 04:23:03

标签: scala scala-collections

根据索引位置,在Scala中仅迭代集合中奇数成员的有效方法是什么?

鉴于此清单:

val fruits: List[String] = List("apples", "oranges", "pears", "bananas")

我想跳过苹果和梨,加工橙子和香蕉。谢谢!

根据给出的回复进行更新:

哇,前三个答案中的每一个都有其优点。我最初的意思是从Scala Collections语法角度来看“有效”这个词,而我实际上只是在寻找一种灵活的方法来为后续迭代创建子列表。 @Senia在引入sliding()函数方面做得很好,非常适合这个特殊用例,但我也喜欢@Brian使用zipWithIndex()的更通用的方法。

然而,当我考虑最初提出的问题的实际措辞以及@ sourcedelica的回复的计算效率时,我认为他会为此获得奖励。

6 个答案:

答案 0 :(得分:16)

scala> List("apples", "oranges", "pears", "bananas").drop(1).sliding(1, 2).flatten.toList
res0: List[java.lang.String] = List(oranges, bananas)

答案 1 :(得分:14)

val fruits: List[String] = List("apples", "oranges", "pears", "bananas")

fruits.zipWithIndex.filter(_._2 % 2 == 1).map(_._1)

res0: List[String] = List(oranges, bananas)

zipWithIndex将List中的每个元素与索引配对:

List[(String, Int)] = List((apples,0), (oranges,1), (pears,2), (bananas,3))

使用filter(_._2 % 2 == 1)过滤奇数元素:

List[(String, Int)] = List((oranges,1), (bananas,3))

将List [(String,Int)]映射到List [String],方法是使用.map(_._1)给出每个元组的第一个元素:

List[String] = List(oranges, bananas)

答案 2 :(得分:7)

这是一种直接迭代奇数的方法:

val fruits: List[String] = List("apples", "oranges", "pears", "bananas")
//> fruits  : List[String] = List(apples, oranges, pears, bananas)

val oddFruitsIterator = 
  Iterator.from(1, 2).takeWhile(_ < fruits.size).map(fruits(_))
//> oddFruits  : Iterator[String] = non-empty iterator

oddFruitsIterator.foreach(println)                      
//> oranges
//> bananas

如果它是一个大型集合和/或您正在进行大量迭代,那么您将首先考虑将其转换为IndexedSeq,以便fruits(_)为O(1)。例如:

val fruitsIs = fruits.toIndexedSeq
val oddFruits = Iterator.from(1, 2).takeWhile(_ < fruitsIs.size).map(fruitsIs(_))

请注意,迭代器本身与它迭代的集合是分开的。这是另一个更清晰的例子:

scala> val oddSeqIterator = 
   (seq: Seq[String]) => Iterator.from(1, 2).takeWhile(_ < seq.size).map(seq(_))
oddSeqIterator: Seq[String] => Iterator[String] = <function1>

scala> val fruits: List[String] = List("apples", "oranges", "pears", "bananas")
fruits: List[String] = List(apples, oranges, pears, bananas)

scala> oddSeqIterator(fruits)
res0: Iterator[String] = non-empty iterator

scala> res0.foreach(println)
oranges
bananas

答案 3 :(得分:1)

我会提出另一种方法,使用递归,在我看来,即使它比其他解决方案更不花哨,它似乎也尽可能少地进行操作。

def iterateOdd(myList:List[String]):List[String] = myList match{
  case _::odd::tail => odd::iterateOdd(tail)
  case _ => Nil
}

或者,如果你只想处理奇怪的成员

def iterateOdd(myList:List[String]):Unit = myList match{
  case _::odd::tail => println(odd); iterateOdd(tail)
  case _ =>   
}

答案 4 :(得分:0)

另一种替代方法是,基于List::grouped的组合以便按对划分项目(这提供了一种方便的方式来访问奇数位置的项目)和Iterator::collect以便处理奇数的集合长度:

// val fruits = List("apples", "oranges", "pears", "bananas", "tomatoes")
fruits.grouped(2).collect { case a :: b => b }.toList
// List("oranges", "bananas")

答案 5 :(得分:-1)

  • 我有另一种解决此类问题的方法。
  • 我们可以利用List.range(开始,结束)方法。

List.range(0,5)将给出List(0,1,2,3,4)

  • 我们可以生成索引列表,我们可以过滤它们

    阶&GT; val fruits:List [String] = List(&#34; apples&#34;,&#34; oranges&#34;,&#34; pears&#34;,&#34; bananas&#34;)

    阶&GT; List.range(0,fruits.length).filter(_%2!= 0).MAP(X =&GT;水果(X))

    res0:List [String] = List(oranges,bananas)