2012-10-08 9 views
10

インデックス位置に基づいて、Scalaのコレクションの奇妙なメンバーだけを効率的に反復する方法はありますか?Scalaのコレクションの奇数メンバーを繰り返します。

は、このリストを考える:

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

私はリンゴと梨、およびプロセスのオレンジやバナナをスキップしたいです。ありがとう!与えられた応答に基づいて

更新:

うわー、トップ3の各回答にはメリットがあります。私はもともと、Scala Collections構文の観点から「効率的」という言葉を意味していました。実際には、後続の反復のためのサブリストを作成するための滑らかな方法を探していました。 @Seniaは、この特定のユースケースに最適なsliding()関数を導入していますが、zipWithIndex()を使用した@Brianのより一般的なアプローチも好きです。

しかし、最初に質問された質問の実際の言い回しと@ 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)] toちょうど一覧[文字列] .map(_._1)寄付して各タプルの最初の要素を取ることによって:、私は別の方法を提案する

List[String] = List(oranges, bananas)

+14

また、 'filter'に続いて' map'があるときはいつでも、 'collect'を使ってそれらを組み合わせることができます。例えば、' fruits.zipWithIndex.collect {case(item、idx)if idx%2 == 1 => item} ' –

+0

非常に良いこの1つの行為の投稿! 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( "リンゴ"、 "オレンジ"、 "梨"、 "バナナ")

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

    s0:リスト[文字列] =リスト(オレンジ、バナナ)

+0

List.range(0,5)はList(0,1,2,3,4)を返します。 –

関連する問題