2012-10-08 47 views
10

什么是有效的方式来遍历Scala中的奇怪成员,基于索引位置?在斯卡拉遍历奇怪的成员集合

鉴于此列表:

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

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

更新基础上给出回应:

哇,每个前三名答案有可取之处。我最初的意思是从Scala Collections语法的角度来看“高效”这个词,我真的只是寻找一种光鲜的方式来为后续的迭代创建子列表。 @Senia做了一个很好的介绍sliding()函数,非常适合这个特殊的用例,但是我也喜欢@ Brian使用zipWithIndex()的更广义的方法。

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

+0

到目前为止,所有答案都没有通过奇数成员进行交互。相反,他们产生一个奇怪成员的列表(当然可以迭代)。但是,必须有一种直接迭代它们的简单方法? –

回答

5

下面是在奇则直接迭代的方式:

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 
15
scala> List("apples", "oranges", "pears", "bananas").drop(1).sliding(1, 2).flatten.toList 
res0: List[java.lang.String] = List(oranges, bananas) 
11
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[(String, Int)] = List((apples,0), (oranges,1), (pears,2), (bananas,3))

滤波器filter(_._2 % 2 == 1)给予奇数元素:

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

映射列表[(String,Int)]到只列出[字符串]抓住每一个元组的第一个元素.map(_._1)捐赠:

List[String] = List(oranges, bananas)

+14

或者,无论何时你有一个'filter'后跟一个'map',你可以用'collect'将它们组合起来,例如'fruits.zipWithIndex.collect {case(item,idx)if ifx%2 == 1 =>项目}' –

+0

非常好的发布这一行动! Scala收集包证明了它在分布式计算中的使用。 –

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 _ => 
} 
-1
  • 我有另一种方法来解决这类问题。
  • 我们可以利用列表。范围(开始,结束)方法。

List.range(0,5)会给列表(0,1,2,3,4)

  • 我们可以生成的索引列表中,我们可以过滤他们

    scala> val fruits:List [String] = List(“apple”,“oranges”,“pear”,“bananas”)

    scala> List.range(0,fruits.length).filter(_%2 != 0).map(x => fruits(x))

    re s0:List [String] = List(oranges,bananas)

+0

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