14

インデックスの位置に基づいて、Scala でコレクションの奇数メンバーのみを反復処理する効率的な方法は何ですか?

このリストを考えると:

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

リンゴとナシを飛ばして、オレンジとバナナを処理したい。ありがとう!

与えられた応答に基づいて更新します。

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

ただし、最初に尋ねられた質問の実際の文言と@sourcedelicaの応答の計算効率を考慮すると、彼はこれに対して賞をとっていると思います。

4

7 に答える 7

18
scala> List("apples", "oranges", "pears", "bananas").drop(1).sliding(1, 2).flatten.toList
res0: List[java.lang.String] = List(oranges, bananas)
于 2012-10-08T04:32:23.723 に答える
17
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)

于 2012-10-08T04:52:06.993 に答える
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
于 2012-10-08T15:59:39.543 に答える
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 _ =>   
}
于 2012-10-08T12:52:15.310 に答える
0

id はスタックを必要とせず、O(1) であるため、tailrec の方が適していると思います。

def f(arr:List[Int]):List[Int] = {
@tailrec
  def loop(source:List[Int],destination:List[Int]):List[Int]= source match {
    case _::odd::tail => loop(tail,destination :+ odd)
    case _ => destination
  }
  loop(arr,List())
}
于 2021-10-18T14:33:10.400 に答える
-1
  • この種の問題を解決する別のアプローチがあります。
  • List.range(start,end) メソッドを利用できます。

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

  • インデックスのリストを生成し、それらをフィルタリングできます

    scala> val fruit: List[String] = List("りんご", "みかん", "梨", "バナナ")

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

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

于 2018-02-03T16:53:22.217 に答える