Scala 中是否有与 Python 更通用的映射函数等效的函数?

发布于 2024-08-28 17:23:29 字数 790 浏览 7 评论 0原文

我知道 Scala 的列表有一个 map 实现,带有签名 (f: (A) => B):List[B]foreach 实现带有签名 ( f: (A) => Unit):Unit 但我正在寻找与 Python map 接受多个迭代。

我正在寻找具有 (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] 或等效签名的东西。是否有一个存在此功能的图书馆或类似的类似方法?

编辑:

正如下面所建议的,我可以这样做,

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

但这会在步骤之间创建一个临时列表。如果评论者发帖,我可以给他投票(提示,提示),但是还有其他方法吗?

I know that Scala's Lists have a map implementation with signature (f: (A) => B):List[B] and a foreach implementation with signature (f: (A) => Unit):Unit but I'm looking for something that accepts multiple iterables the same way that the Python map accepts multiple iterables.

I'm looking for something with a signature of (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] or equivalent. Is there a library where this exists or a comparable way of doing similar?

Edit:

As suggested below I could do

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

but that creates a temporary list in between steps. If the commentor would post I could upvote him (hint, hint) but is there another way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

仅此而已 2024-09-04 17:23:29

在 scala 2.8 中,Tuple2 & 中有一个名为 zipped 的方法。 Tuple3避免创建临时集合。
以下是一些示例用例:

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).zipped 中也存在一些不足,请确保xs 不可能是无限流。请访问票证 #2634 了解更多信息。
我有一篇文章 显示了我对如何修复此票证的看法。

In scala 2.8, there is a method called zipped in Tuple2 & Tuple3 which avoid to create temporary collection.
Here is some sample use case:

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>

There is a zip method in both Tuple2 and Tuple3.
xs.zip(ys) is the same as (xs,ys).zip

Note: There is also some shortage in (xs,ys).zip and (xs,ys).zipped, make sure that xs can't be a INFINITE Stream. Go to Ticket #2634 for more information.
I have a post in nabble.com some days ago which shows my opinions about how to fix this ticket.

×眷恋的温暖 2024-09-04 17:23:29

您要查找的函数通常称为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 实现是完全惰性的。

但为什么要停留在Iterable呢?这具有更一般的形式。我们可以为所有可以通过这种方式压缩的数据结构声明一个接口。

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

例如,我们可以压缩函数:

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库为标准库中的大量数据结构提供了Applicative实例。此外,还为 ap 提供了方便的语法。在 Scalaz 中,此函数称为 <*>

def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
  (a map f) <*> b

The function you're looking for is usually called zipWith. It's unfortunately not provided in the standard libraries, but it's pretty easy to write:

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
  }

This will traverse only once, since the implementations for zip and map on iterators are fully lazy.

But why stop at Iterable? This has an even more general form. We could declare an interface for all data structures that can be zipped this way.

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

For example, we can zip functions:

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))
}

There turns out to be an even more general expression of this type. In general, type constructors that allow an implementation of this interface are applicative functors

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]
}

An implementation of zipWith is then just this:

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)

This generalises to functions of any arity:

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

The Scalaz library provides Applicative instances for a lot of data structures in the standard library. Also, convenient syntax is provided for ap. In Scalaz, this function is called <*>:

def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) =
  (a map f) <*> b
记忆消瘦 2024-09-04 17:23:29

Scala 2.7(和 2.8,但已弃用,改用 zipped)的 List 对象中有一个 map2 方法。你可以像这样使用它:

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

Eastsun 已经在 2.8 中展示了如何使用zipped(它适用于所有集合,而不仅仅是列表)。

There is a method map2 in the List object in Scala 2.7 (and 2.8, but it's deprecated in favor of zipped). You use it like so:

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

Eastsun's already shown how to use zipped in 2.8 (which works on all collections, not just lists).

祁梦 2024-09-04 17:23:29

好吧,我不知道语法 (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] (我对 Scala 一无所知),但如果我不得不猜测,这意味着“一个函数 f 接受两个可迭代参数 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 函数:enumeratemapreducezipfilter 曾经位于该列表中,但现在使用列表理解更清晰、更灵活。

Well, I don't know the syntax (f: (A,B) => C, Iterable[A], Iterable[B] ):Iterable[C] (and I know nothing of Scala), but if I had to guess, it would mean "A function f taking two iterable arguments A and B and returning an iterable C". I'm not sure if this implies that all iterables yield the same number of items.

In Python, I think you're looking for the zip function:

>>> 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's output is only as long as the shortest iterable:

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

Anyway, some built-in Python functions everyone needs to know but easily misses: enumerate, map, reduce, and zip. filter used to be on that list, but it's clearer and more flexible to use a list comprehension these days.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文