9

Scalaのリストには署名付きのマップ実装と署名付き(f: (A) => B):List[B]foreach実装があることは知っていますが、Pythonマップ(f: (A) => Unit):Unitが複数の反復可能オブジェクトを受け入れるのと同じ方法で複数の反復可能オブジェクトを受け入れるものを探しています。

(f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C]の署名または同等のものを探しています。これが存在するライブラリ、または同様のことを行う同等の方法はありますか?

編集:

以下に提案するように、私はできる

val output = myList zip( otherList ) map( x => x(0) + x(1) )

しかし、それはステップの間に一時的なリストを作成します。コメント投稿者が投稿する場合、私は彼に賛成することができます(ヒント、ヒント)が、別の方法はありますか?

4

4 に答える 4

12

Scala 2.8には、一時的なコレクションの作成を回避する、Tuple2とTuple3にzipされたというメソッドがあります。いくつかのサンプルユースケースを次に示します。

Welcome to Scala version 2.8.0.r21561-b20100414020114 (Java HotSpot(TM) Client VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val xs = 0 to 9
xs: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val ys = List.range(0,10)
ys: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val zs = Array.range(0,10)
zs: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> (xs,ys).zipped.map{ _+_ }
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)

scala> (zs,ys,xs).zipped.map{ _+_+_ }
res2: Array[Int] = Array(0, 3, 6, 9, 12, 15, 18, 21, 24, 27)

scala>

Tuple2とTuple3の両方にzip方式があります。xs.zip(ys)は(xs、ys).zipと同じです

注:(xs、ys).zipと(xs、ys).zipにはいくつかの不足もあります。xsがINFINITEストリームにならないようにしてください。詳細については、チケット#2634にアクセスしてください。数日前にnabble.comに投稿があり、このチケットを修正する方法についての私の意見が示されています。

于 2010-04-16T07:07:49.763 に答える
11

あなたが探している関数は通常と呼ばれzipWithます。残念ながら、標準ライブラリでは提供されていませんが、次のように書くのは非常に簡単です。

def zipWith[A,B,C](f: (A,B) => C, a: Iterable[A], b: Iterable[B]) =
  new Iterable[C] {
    def elements = (a.elements zip b.elements) map f.tupled
  }

イテレータの実装は完全に怠惰であるためzip、これは1回だけトラバースします。map

しかし、なぜ立ち止まるのIterableですか?これはさらに一般的な形式です。この方法で圧縮できるすべてのデータ構造のインターフェースを宣言できます。

trait Zip[F[_]] {
  def zipWith[A,B,C](f: (A,B) => C, a: F[A], b: F[B]): F[C]
}

たとえば、関数をzipできます。

trait Reader[A] {
  type Read[B] = (A => B)
}

def readerZip[T] = new Zip[Reader[T]#Read] {
  def zipWith[A,B,C](f: (A,B) => C, a: T => A, b: T => B): T => C =
    (t: T) => f(a(t),b(t))
}

このタイプのさらに一般的な表現があることが判明しました。一般に、このインターフェースの実装を可能にする型構築子は、適用可能なファンクターです。

trait Applicative[F[_]] {
  def pure[A](a: A): F[A]
  def map[A,B](f: A => B, a: F[A]): F[B]
  def ap[A,B](f: F[A => B], a: F[A]): F[B]
}

zipWithの実装は次のようになります。

def zipWith[F[_],A,B,C](f: A => B => C, a: F[A], b: F[B])
                       (implicit m: Applicative[F]) =
  m.ap(m.map(f,a), b)

これは、あらゆるアリティの機能に一般化されます。

  m.ap(m.ap(m.ap(m.map(f,a), b), c), d)

Scalazライブラリは、標準ライブラリの多くのデータ構造に適用可能なインスタンスを提供しますまた、便利な構文が。に提供されていapます。Scalazでは、この関数は次のように呼ばれ<*>ます。

def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
  (a map f) <*> b
于 2010-04-16T13:29:47.073 に答える
3

Scala 2.7(および2.8)map2のオブジェクトにはメソッドがありますが、廃止されて)になりました。あなたはそれを次のように使用します:Listzipped

List.map2( List(1,2,3) , List(4,5,6) ) { _ * _ }  // Gives List(4,10,18)

Eastsunはzipped、2.8での使用方法をすでに示しています(リストだけでなく、すべてのコレクションで機能します)。

于 2010-04-16T12:12:58.923 に答える
2

構文はわかりませんが(Scalaについては何も(f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C]知りません)、推測すると、「関数fが2つの反復可能な引数ABを取り、反復可能なCを返す」という意味になります。これが、すべての反復可能オブジェクトが同じ数のアイテムを生成することを意味するかどうかはわかりません。

Pythonでは、 zip関数を探していると思います。

>>> A = range(10, 15)
>>> B = range(1000, 1500, 100)
>>> zip(A, B)
[(10, 1000), (11, 1100), (12, 1200), (13, 1300), (14, 1400)]
>>> [a + b for a,b in zip(A, B)]
[1010, 1111, 1212, 1313, 1414]

zipの出力は、反復可能な最短の長さだけです。

>>> A=range(10, 12)
>>> zip(A, B)
[(10, 1000), (11, 1100)]

とにかく、一部の組み込みPython関数は、誰もが知っておく必要がありますが、簡単に見逃してしまいます:enumerate、、、、。 以前はそのリストに含まれていましたが、最近ではリスト内包表記を使用する方が明確で柔軟性があります。mapreducezipfilter

于 2010-04-16T12:17:14.043 に答える