2012-10-08 46 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) –