4

欠落している値が含まれている可能性のあるリストに対して、いくつかの算術演算を実行しようとしています。これまでのところ、Option[Int]でリストを表しています。

val mylist=List( Option(4), Option(8), None )

この表現を使用すると、リストに関数を簡単に適用できます(たとえば、2を掛けます)。

scala> mylist.map(_.map(_*2))
res2: List[Option[Int]] = List(Some(8), Some(16), None)

しかし、これは必要以上に複雑に見えるので、何かが足りないのではないかと思います。

また、和のような書き方がわかりません。(大きな)reduce式で可能になるはずです...

だから、私は知りたいのです:

  • List [Option [Int]]は、このユースケースの適切な表現です
  • mylist.map(_.map(_*2))マップするための最良の方法です
  • 合計を行う簡単な方法はありますか?
4

5 に答える 5

1

まあ、それは私が自分で使用したパターンではありませんが、値が「欠落」している可能性がある場合は、Optionが適切です。しかし、Listおそらくそうではありません。Listランダムアクセスではないため、ポジションでは通常、信頼できるものではありません。たぶん、aのVector方が良いでしょう。あるいは、問題をモデル化するためのより良い方法を考える必要があります。つまり、値が欠落しているリストとしてではありません。

Optionfor-expressionsを使用してうまく処理できます。

for (o <- mylist; x <- o) yield x * 2

またはリストをフラット化します。

mylist.flatten.map(_ * 2)

要約すると:

mylist.flatten.sum
于 2012-11-25T03:09:31.797 に答える
1
  • List [Option [Int]]は、このユースケースの適切な表現です

flatMapで以前にフラット化することは可能ですか?たとえば、mapを使用してこのリストを作成している場合は、代わりにflatMapを使用して、値が欠落しないようにすることができます。私の提案は、可能であれば、欠落している値を表現することすらしないことです。それらを表現する必要がある場合は、Optionが理想的です。

  • mylist.map(_.map(_*2))マップするための最良の方法です
  • 合計を行う簡単な方法はありますか?

ネストされたマップがおそらく望ましいです。あなたfoldLeftもできます。

foldLeftsum/product以外のことをする必要がある場合にも役立ちます。

scala> val mylist=List( Option(4), Option(8), None )
mylist: List[Option[Int]] = List(Some(4), Some(8), None)

scala> mylist.foldLeft(0){
     |   case (acc, Some(i)) => acc + i 
     |   case (acc, _) => acc
     | }
res7: Int = 12

scala> (0 /: mylist) {
     |   case (acc, Some(i)) => acc + i 
     |   case (acc, _) => acc
     | }
res8: Int = 12

scala> (0 /: mylist) {
     |   case (acc, Some(i)) => acc - (i * 2)
     |   case (acc, _) => acc
     | }
res16: Int = -24
于 2012-11-25T03:35:35.287 に答える
0

これを行う最も一般的で簡潔な方法は、Scalazの semigroup 型クラスを使用することです。そうすれば、に制限されることはありませんList[Option[Int]]が、同じ機能を に適用できますList[Int]

import scalaz._
import Scalaz._

object S {
  def double[A:Semigroup](l:List[A]) = l.map(x => x |+| x)
  def sum[A:Semigroup](l:List[A]) = l.reduce(_ |+| _)

  def main(a:Array[String]) {
    val l = List(Some(1), None, Some(2))
    val l2 = List(1,2)
    println(double(l))
    println(sum(l))
    println(double(l2))
    println(sum(l2))
  }

}

これは印刷します

List(Some(2), None, Some(4))
Some(3)
List(2, 4)
3
于 2012-11-25T07:22:13.610 に答える
0

あなたが達成しようとしていることはわかりませんが、これは正しいアプローチではないようです。「リスト」に値が存在するかどうかを判断する必要がある場合は、おそらくSetあなたのニーズに合うでしょう:

scala> val s = Set(4,8)
s: scala.collection.immutable.Set[Int] = Set(4, 8)

scala> s(4)
res0: Boolean = true

scala> s(5)
res1: Boolean = false

scala> s map (_ * 2)
res2: scala.collection.immutable.Set[Int] = Set(8, 16)

scala> s reduceLeft((a,b) => a+b)
res3: Int = 12

またはさらに簡単:

scala> s sum
res4: Int = 12

より洗練されたものが必要で、リスト内の要素のインデックスが重要な場合はMap、キーがインデックスをシミュレートする場所を使用できます。欠損値はデフォルト値にマップできます。

scala> val m = Map(1 -> 4, 2 -> 8) withDefault(n => 0)
m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 4, 2 -> 8)

scala> m(1)
res5: Int = 4

scala> m(3)
res6: Int = 0

scala> m map {case (k,v) => (k,2*v)}
res7: scala.collection.immutable.Map[Int,Int] = Map(1 -> 8, 2 -> 16)

scala> m.foldLeft(0){case (sum,(_,v)) => sum+v}
res8: Int = 12

繰り返しますが、あなたのニーズが何であるかはわかりませんが、間違った方向に進んでいるように感じます...
Option使用する前によく考えるタイプです. 本当に必要かどうか自問してください。あなたがやろうとしていることをよりエレガントな方法で達成する解決策があるかもしれません。

于 2012-11-25T12:13:53.683 に答える
0

だから、私は知りたい:

List[Option[Int]] は、このユースケースの適切な表現です

オプションは、欠損値を表現するための望ましい方法であることは間違いありません。List[(Int, Int)]最初の要素が元のリスト内の位置を示し、2 番目の要素が値を表すように変更することも考えられます。

mylist.map(_.map(_*2))マッピングするのに最適な方法です

私の意見では、それを表現するためのより短くてきれいな方法はありません。(2 つの「レベル」があるため、2 つのマップが必要です!) 私が提案したデータ構造では、これはmylist.map(t => (t._1, t._2*2)).

合計を行う簡単な方法はありますか?

om-nom-nom が提案するよりも簡単な方法はありません。私のデータ構造では、mylist.map(_._2).sum

于 2012-11-25T03:51:21.023 に答える