Scala 使用map函数将两个seq转换为一个seq。斯卡拉
在clojure中,我们有一个映射函数,您可以在其中提供一个函数和两个集合Scala 使用map函数将两个seq转换为一个seq。斯卡拉,scala,functional-programming,for-comprehension,Scala,Functional Programming,For Comprehension,在clojure中,我们有一个映射函数,您可以在其中提供一个函数和两个集合 (map + [1 2 ] [4 5 ]) ;;=> (5 7 ) Scala中有类似的东西吗 我试着理解,但后来我得到了4个组合 如果有一种理解的方法,那就更好了,因为我以后要做一些过滤/您可以先使用.zip将两个集合合并为一个,然后映射: seq1.zip(seq2).map { case (x, y) => x + y } 我认为这不可能有一个令人理解的答案。您也可以通过调用.filter或.fil
(map + [1 2 ] [4 5 ]) ;;=> (5 7 )
Scala中有类似的东西吗
我试着理解,但后来我得到了4个组合
如果有一种理解的方法,那就更好了,因为我以后要做一些过滤/您可以先使用
.zip
将两个集合合并为一个,然后映射:
seq1.zip(seq2).map { case (x, y) => x + y }
我认为这不可能有一个令人理解的答案。您也可以通过调用
.filter
或.filterNot
进行筛选。您可以先使用.zip
将两个集合合并为一个,然后映射:
seq1.zip(seq2).map { case (x, y) => x + y }
我认为这不可能有一个令人理解的答案。您也可以通过调用
.filter
或.filterNot
来进行筛选。这里没有添加任何新内容,但这可能会有所帮助:
def mapCollections[A,B,C](as: Seq[A], bs: Seq[B])(f: (A,B) => C): Seq[C] =
as zip bs map f.tupled
mapCollections(List(1, 2), List(4, 5))(_ + _) // = List(5, 7)
这里没有添加任何新内容,但这可能会有所帮助:
def mapCollections[A,B,C](as: Seq[A], bs: Seq[B])(f: (A,B) => C): Seq[C] =
as zip bs map f.tupled
mapCollections(List(1, 2), List(4, 5))(_ + _) // = List(5, 7)
@乔克给了你具体的答案 我将为您提供两个更一般的答案。Clojure和许多其他动态语言通常会抽象出过多的内容(标准库的
map
和apply
函数就是很好的例子)。在缺少依赖类型的情况下,在静态类型语言中很难做到这一点。您将看到的一般模式是根据需要多次重复应用函数。在这种情况下,如果你需要这样做
(map + [1 2 3] [4 5 6] [7 8 9])
你需要这样做
xs.zip(ys).zip(zs).map{ case (x, (y, z)) => x + y + z }
一般来说,这个额外的样板并不可怕。当您想要在任意元组或任意case类上进行抽象时,对arity的抽象就变得更加难以理解了。这时,一个提供有限形式的依赖类型的Scala库开始发挥作用
不过,我不会为了这样的事情而变得不成形
第二个要点是,你不能按照你要求的方式来压缩列表(一般来说不是这样的……因为你可以在Scala中对所有内容进行平等性比较,你可以用一个最终的过滤过程,但如果内置的平等性不能给你想要的东西,那么这就失败了)。这背后的一般原则有点微妙。事实证明,这些收集函数有一个层次结构。从map
开始。如果添加zip
和List.apply,则跳到下一级。如果将zip
替换为flatte
,您将获得另一个级别。使用flatte
可以恢复zip
的一个版本,但反过来就不行了
集合的默认ScalaflatMap
和flatMap
(请注意,理解的最终目的是一系列flatMap
调用)确实会产生一种形式的zip
,即具有相同类型签名的东西,但正如您所注意到的,它是笛卡尔积
有一个版本的flatte
确实产生了标准的zip
,但它只有在所有收藏长度相同的情况下才有意义。它涉及从集合集合中得到的平方矩阵的对角线
这对于有限集合通常不太有用,因为Scala的类型系统不足以表示常量长度约束,如果不确保长度一致,可能会出现一些奇怪的行为
另一方面,这是flatte
和flatMap
的版本,它实际上对无限流有用(其中List.apply
的等价物是无限恒定流),而flatte
的“正常”版本将无法通过对第一个流的处理
旁注:您当然可以在以后的应用程序中使用压缩列表进行理解(您可以在其中进行一些过滤)。你只是不能用一种简单的方式来实现压缩本身,以便于理解。@JoeK给出了具体的答案
我将为您提供两个更一般的答案。Clojure和许多其他动态语言通常会抽象出过多的内容(标准库的map
和apply
函数就是很好的例子)。在缺少依赖类型的情况下,在静态类型语言中很难做到这一点。您将看到的一般模式是根据需要多次重复应用函数。在这种情况下,如果你需要这样做
(map + [1 2 3] [4 5 6] [7 8 9])
你需要这样做
xs.zip(ys).zip(zs).map{ case (x, (y, z)) => x + y + z }
一般来说,这个额外的样板并不可怕。当您想要在任意元组或任意case类上进行抽象时,对arity的抽象就变得更加难以理解了。这时,一个提供有限形式的依赖类型的Scala库开始发挥作用
不过,我不会为了这样的事情而变得不成形
第二个要点是,你不能按照你要求的方式来压缩列表(一般来说不是这样的……因为你可以在Scala中对所有内容进行平等性比较,你可以用一个最终的过滤过程,但如果内置的平等性不能给你想要的东西,那么这就失败了)。这背后的一般原则有点微妙。事实证明,这些收集函数有一个层次结构。从map
开始。如果添加zip
和List.apply,则跳到下一级。如果将zip
替换为flatte
,您将获得另一个级别。使用flatte
可以恢复zip
的一个版本,但反过来就不行了
集合的默认ScalaflatMap
和flatMap
(请注意,理解的最终目的是一系列flatMap
调用)确实会产生一种形式的zip
,即具有相同类型签名的东西,但它最终证明是笛卡尔积