2

この簡単な例のように、各要素のインクリメンタル シャドウイングを使用して、コレクション内の各要素の関数を計算する最良の方法は何ですか?

val v = IndexedSeq(1,2,3,4)

v.shadowMap{ e => e + 1}

shadow 1: (3,4,5)
shadow 2: (2,4,5)
shadow 3: (2,3,5)
shadow 4: (2,3,4)

これを最初に作成するpatchか、作成することを考えsliceていますが、純粋に機能的なスタイルでそれを行うためのより良い方法があるのではないでしょうか?

ありがとうございます。

4

3 に答える 3

3
def shadowMap[A,B](xs: Seq[A])(f: A => B) = {
  val ys = xs map f
  for (i <- ys.indices; (as, bs) = ys splitAt i) yield as ++ bs.tail
}
于 2012-07-24T20:22:32.103 に答える
2

次のように定義できます。

class ShadowMapSeq[A, Repr <: Seq[A]](seq: SeqLike[A, Repr]) {
  def shadowMap[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): Iterator[That] = {
    seq.indices.iterator.map { i =>
      val b = bf(seq.asInstanceOf[Repr])
      b.sizeHint(seq.size - 1)
      b ++= (seq.take(i) ++ seq.drop(i + 1)).map(f)
      b.result
    }
  }
}
implicit def shadowMapSeq[A, Repr <: Seq[A]](seq: SeqLike[A, Repr]) = new ShadowMapSeq(seq)

そして、次のように使用します。

scala> val v = IndexedSeq(1, 2, 3, 4)
scala> val results = v.shadowMap(_ + 1)
scala> results foreach println
Vector(3, 4, 5)
Vector(2, 4, 5)
Vector(2, 3, 5)
Vector(2, 3, 4)
于 2012-07-24T18:03:13.403 に答える
1

「純粋な機能スタイル」とは、「インデックスを参照せずに」のようなものを意味する場合 (と を避けたいと言っているためpatch) 、ジッパーsliceを使用してこれをかなりエレガントに行うことができます。たとえば、Scalaz のジッパーの実装を使用してそれを記述する方法は次のとおりです (これは単なるデモです。よりうまくまとめたい場合は、dhg が彼の回答で示したアプローチを使用できます)。

import scalaz._, Scalaz._

List(1, 2, 3, 4).map(_ + 1).toZipper.map(
   _.positions.map(p => (p.lefts.reverse ++ p.rights).toList).toStream
).flatten

一般的には、実際のコードで dhg のソリューションを使用する方がよいでしょうが、zipper は知っておくと便利なデータ構造であり、この問題に適しています。

于 2012-07-24T18:34:12.747 に答える