ScalaにPythonのより一般的なマップ機能に相当するものはありますか?
-
27-09-2019 - |
質問
Scalaのリストにはaがあります 地図 署名による実装 (f: (A) => B):List[B]
そしてa foreach 署名による実装 (f: (A) => Unit):Unit
しかし、私はPythonと同じ方法で複数の反復可能性を受け入れるものを探しています 地図 複数の反復可能性を受け入れます。
私は署名のあるものを探しています (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C]
または同等の。これが存在するライブラリや、同様のことをする匹敵する方法はありますか?
編集:
以下で示唆したように、私はすることができました
val output = myList zip( otherList ) map( x => x(0) + x(1) )
しかし、それはステップの間に一時的なリストを作成します。コメンターが投稿した場合、私は彼を賛成することができます(ヒント、ヒント)が、別の方法はありますか?
解決
Scala 2.8には、Tuple2&Tuple3にzippedと呼ばれる方法があり、一時的なコレクションを作成することを避けています。サンプルユースケースは次のとおりです。
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).ziptにも不足があり、xsが無限のストリームにならないことを確認してください。行きます チケット#2634 詳細については。私は持っています ポスト 数日前にNabble.comで、このチケットを修正する方法についての私の意見を示しています。
他のヒント
あなたが探している関数は通常呼ばれます 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
と map
イテレーターには完全に怠zyです。
しかし、なぜ立ち止まるのか 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)
スカラズ ライブラリは、標準ライブラリの多くのデータ構造に適用インスタンスを提供します。また、便利な構文が提供されています ap
. 。 Scalazでは、この関数が呼び出されます <*>
:
def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
(a map f) <*> b
方法があります map2
の中に List
SCALA 2.7のオブジェクト(および2.8ですが、それは有利に廃止されています zipped
)。あなたはそうするようにそれを使用します:
List.map2( List(1,2,3) , List(4,5,6) ) { _ * _ } // Gives List(4,10,18)
Eastsunはすでに使用方法を示しています zipped
2.8(リストだけでなく、すべてのコレクションで機能します)。
まあ、私はしません 知る 構文 (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C]
(そして、私は知っています なし SCALAの)、しかし、私が推測しなければならなかった場合、それは「機能」を意味します f 2つの反復的な引数を取得します a と b 反復可能なものを返します c「。これがすべての反復可能性が同じ数のアイテムを生成することを意味するかどうかはわかりません。
Pythonでは、あなたが探していると思います ジップ 働き:
>>> 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
, map
, reduce
, 、 と zip
. filter
以前はそのリストに載っていましたが、最近ではリストの理解を使用する方が明確で柔軟です。