使用map函数将两个seq转换为一个。阶

时间:2017-09-11 22:34:30

标签: scala functional-programming for-comprehension

在clojure中我们有一个map函数,你可以在其中提供一个函数和两个集合

(map + [1 2 ] [4 5 ]) ;;=> (5 7 )

Scala中有类似内容吗?

我试着理解,但后来我得了4个组合。

如果有一种方法可以理解,会更好,因为我将来必须做一些过滤/

3 个答案:

答案 0 :(得分:5)

您可以先使用.zip将两个集合合并为一个,然后映射:

seq1.zip(seq2).map { case (x, y) => x + y }

我不认为这是理解的可能性。您也可以通过拨打.filter.filterNot进行过滤。

答案 1 :(得分:1)

@JoeK为您​​提供了具体的答案。

我将为您提供两个更一般的答案。 Clojure和许多其他动态语言经常会在arity上进行抽象(标准库的mapapply函数就是很好的例子)。在没有依赖类型的情况下,这在静态类型语言中很难做到。您将看到的一般模式是根据需要多次重复应用函数。在这种情况下,如果你需要做

(map + [1 2 3] [4 5 6] [7 8 9])

你需要做

xs.zip(ys).zip(zs).map{ case (x, (y, z)) => x + y + z }

通常这个额外的样板并不可怕。当你想要抽象任意元组或任意案例类时,对于arity的抽象变得更加严重错过的地方。当Shapeless,一个Scala库为您提供有限形式的依赖类型时,就会发挥作用。

我不会因为这样的事情而打破Shapeless。

第二个一般观点是,你不能以你理解的方式输入列表(一般情况下不是这样...因为你可以比较Scala中的所有内容,你有点可以用一个最终的过滤器通过,但对于内置相等并不能满足你想要的任何东西都会失败。这背后的一般原则是更微妙的。事实证明,这些集合函数的权力等级。你从map开始。如果您添加zipList.apply,则会跳转到下一个级别。如果您将zip替换为flatten,则会获得另一个级别。使用flatten,您可以恢复zip的版本,但不能相反。

对于集合,默认Scala flatMapflatten(请注意,对于理解最终是一系列flatMap调用)确实会产生zip形式,即具有相同类型签名的东西,但事实证明它是笛卡尔产品。

flatten的版本确实会产生标准zip,但只有当所有的集合长度相同时才有意义。它涉及从集合集合中获取方形矩阵的对角线。

这对于有限集合通常不那么有用,因为Scala的类型系统不足以表达恒定长度约束,如果你不确保长度一致,你会得到一些奇怪的行为。

另一方面,这是flattenflatMap的版本,它实际上对无限流有用(其中等价的List.apply是无限常量流)而#&# 34;正常"版本flatten无法通过处理第一个流。

旁注:您当然可以在以后总是使用您的压缩列表进行理解(您可以在其中进行一些过滤)。你无法在理解中实现拉链本身。

答案 2 :(得分:0)

这里并没有真正添加任何新内容,但也许这会有所帮助:

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)