组合 2 个列表的元素

发布于 2025-01-03 04:58:57 字数 467 浏览 5 评论 0原文

假设我们有两个列表:

val l1=List("a","b","c")
val l2 = List("1","2","3")

我想要的是: List("a1", "b2", "c3") 也就是说,将 l1 的第 n 个元素与 l2 的第 n 个元素

相加实现它是:

(l1 zip l2).map (c => {c._1+c._2})

我只是想知道是否可以通过应用程序来实现它。我尝试过:

(l1 |@| l2) { _+ _ } 

但它给出了所有组合:

List(a1, a2, a3, b1, b2, b3, c1, c2, c3)

有什么想法吗?

谢谢伯努瓦

Assume we have two lists :

val l1=List("a","b","c")
val l2 = List("1","2","3")

What I want is : List("a1", "b2", "c3") that is, adding the nth element of l1 with the nth element of l2

A way to achieve it is :

(l1 zip l2).map (c => {c._1+c._2})

I just wonder if one could achieve it with an Applicative. I tried :

(l1 |@| l2) { _+ _ } 

but it gives all the combinations :

List(a1, a2, a3, b1, b2, b3, c1, c2, c3)

Any idea?

Thank you

Benoit

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

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

发布评论

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

评论(2

缪败 2025-01-10 04:58:57

您不能使用严格列表来做到这一点,因此请使用惰性列表,即流。您必须定义 Applicative[Stream] 实例,如下所示。 (您可以在 Haskell 标准库中以 ZipList 的名称找到它。)

scala> val s1 = Stream("a", "b", "c")
s1: scala.collection.immutable.Stream[java.lang.String] = Stream(a, ?)

scala> val s2 = Stream("1", "2", "3")
s2: scala.collection.immutable.Stream[java.lang.String] = Stream(1, ?)

scala> implicit object StreamApplicative extends Applicative[Stream] {
     |   def pure[A](a: => A) = Stream.continually(a)
     |   override def apply[A, B](f: Stream[A => B], xs: Stream[A]): Stream[B] = (f, xs).zipped.map(_ apply _)
     | }
defined module StreamApplicative

scala> (s1 |@| s2)(_ + _)
res101: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, ?)

scala> .force
res102: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, b2, c3)

不能使用严格列表来完成此操作的原因是因为不可能在它们上定义满足应用法则的pure

顺便说一句,Scala 可以让您比 OP 中使用的代码更简洁地完成此操作:

scala> (l1, l2).zipped.map(_ + _)
res103: List[java.lang.String] = List(a1, b2, c3)

You cannot do that with strict lists, so instead use lazy lists i.e. streams. You have to define the Applicative[Stream] instance as shown below. (You'll find it in Haskell standard library under the name ZipList.)

scala> val s1 = Stream("a", "b", "c")
s1: scala.collection.immutable.Stream[java.lang.String] = Stream(a, ?)

scala> val s2 = Stream("1", "2", "3")
s2: scala.collection.immutable.Stream[java.lang.String] = Stream(1, ?)

scala> implicit object StreamApplicative extends Applicative[Stream] {
     |   def pure[A](a: => A) = Stream.continually(a)
     |   override def apply[A, B](f: Stream[A => B], xs: Stream[A]): Stream[B] = (f, xs).zipped.map(_ apply _)
     | }
defined module StreamApplicative

scala> (s1 |@| s2)(_ + _)
res101: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, ?)

scala> .force
res102: scala.collection.immutable.Stream[java.lang.String] = Stream(a1, b2, c3)

The reason this cannot be done with strict lists is because it is impossible to define a pure on them that satisfies the applicative laws.

As an aside, Scala lets you do this more concisely than the code you have used in OP:

scala> (l1, l2).zipped.map(_ + _)
res103: List[java.lang.String] = List(a1, b2, c3)
眼泪都笑了 2025-01-10 04:58:57

答案是,据我所知,你无法通过应用程序来实现这一目标。正如您所发现的,列表的应用程序会将函数应用于所有组合。不太适合您想要的东西,但对于创建笛卡尔积之类的东西来说很棒。

稍微不那么冗长的方法可能会使用 scalaz 提供的 Tuple2W.fold

(l1 zip l2).map (_ fold (_ + _))

The answer is that you can't achieve this with an applicative as far as I can see. The applicative for list will apply the function to all combinations, as you have found out. Not great for what you want but awesome for stuff like creating cartesian products.

A slightly less verbose method might use Tuple2W.fold supplied by scalaz:

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