Scala-yield 可以在 for 循环中多次使用吗?

发布于 2024-07-27 21:55:53 字数 203 浏览 3 评论 0原文

举个例子:

val l = List(1,2,3)
val t = List(-1,-2,-3)

我可以做这样的事情吗?

for (i <- 0 to 10) yield (l(i)) yield (t(i))

基本上我想为每次迭代产生多个结果。

An example:

val l = List(1,2,3)
val t = List(-1,-2,-3)

Can I do something like this?

for (i <- 0 to 10) yield (l(i)) yield (t(i))

Basically I want to yield multiple results for every iteration.

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

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

发布评论

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

评论(6

谁的新欢旧爱 2024-08-03 21:55:53

目前尚不清楚您要求什么 - 您期望多重收益的语义是什么。 但有一点是,您可能永远不想使用索引来导航列表 - 每次调用 t(i) 的执行时间都是 O(i)。

所以这是您可能会要求的一种可能性

scala> val l = List(1,2,3); val t = List(-1,-2,-3)
l: List[Int] = List(1, 2, 3)
t: List[Int] = List(-1, -2, -3)

scala> val pairs = l zip t
pairs: List[(Int, Int)] = List((1,-1), (2,-2), (3,-3))

这是您可能会要求的另一种可能性

scala> val crossProduct = for (x <- l; y <- t) yield (x,y)
crossProduct: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

后者只是语法糖

scala> val crossProduct2 = l flatMap {x => t map {y => (x,y)}}
crossProduct2: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

第三种可能性是您想要交错它们

scala> val interleaved = for ((x,y) <- l zip t; r <- List(x,y)) yield r
interleaved: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)

这是语法糖

scala> val interleaved2 = l zip t flatMap {case (x,y) => List(x,y)}
interleaved2: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)

It's not clear what you're asking for - what you expect the semantics of multiple yield to be. One thing, though, is that you probably never want to use indexes to navigate a list - each call to t(i) is O(i) to execute.

So here's one possibility that you might be asking for

scala> val l = List(1,2,3); val t = List(-1,-2,-3)
l: List[Int] = List(1, 2, 3)
t: List[Int] = List(-1, -2, -3)

scala> val pairs = l zip t
pairs: List[(Int, Int)] = List((1,-1), (2,-2), (3,-3))

And here's another possibility that you might be asking for

scala> val crossProduct = for (x <- l; y <- t) yield (x,y)
crossProduct: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

The later is just syntactic sugar for

scala> val crossProduct2 = l flatMap {x => t map {y => (x,y)}}
crossProduct2: List[(Int, Int)] = List((1,-1), (1,-2), (1,-3), (2,-1), (2,-2), (2,-3), (3,-1), (3,-2), (3,-3))

A third possibility is you want to interleave them

scala> val interleaved = for ((x,y) <- l zip t; r <- List(x,y)) yield r
interleaved: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)

That's syntax sugar for

scala> val interleaved2 = l zip t flatMap {case (x,y) => List(x,y)}
interleaved2: List[Int] = List(1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8, 9, -9, 10, -10)
不弃不离 2024-08-03 21:55:53

不,您不能使用多个yield 子句,但有一些解决方法。 例如:

for (i <- 0 to 10;
     r <- List(l(i), t(i)))
yield r

当然,您可以嵌套 for 推导式,但这会产生一个元素列表的列表,我认为这不是您想要的。

No, you can't use multiple yield clauses, but there are work-arounds. For example:

for (i <- 0 to 10;
     r <- List(l(i), t(i)))
yield r

You can nest for-comprehensions, of course, but that would result in a list of lists of elements, which I don't believe is what you want.

很酷不放纵 2024-08-03 21:55:53

产量可以嵌套,这会导致......

for (i <- 0 to 3) yield {
  for (j <- 0 to 2) yield (i,j)
}

向量的向量:

scala.collection.immutable.IndexedSeq[scala.collection.immutable.IndexedSeq[(Int, Int)]]
= Vector(Vector((0,0), (0,1), (0,2)), Vector((1,0), (1,1), (1,2)), Vector((2,0), (2,1), (2,2)), Vector((3,0), (3,1), (3,2)))

for (i <- 0 to 3;
  j <- 0 to 2) yield (i,j)

扁平化的解决方案在语义上是不同的。

Yields can be nested, which would result ...

for (i <- 0 to 3) yield {
  for (j <- 0 to 2) yield (i,j)
}

in a Vector of Vector:

scala.collection.immutable.IndexedSeq[scala.collection.immutable.IndexedSeq[(Int, Int)]]
= Vector(Vector((0,0), (0,1), (0,2)), Vector((1,0), (1,1), (1,2)), Vector((2,0), (2,1), (2,2)), Vector((3,0), (3,1), (3,2)))

for (i <- 0 to 3;
  j <- 0 to 2) yield (i,j)

The flattened solution is semantically different.

述情 2024-08-03 21:55:53

这是一个与类型无关的解决方案,适用于未知数量的列表中未知的、变化数量的元素:

def xproduct (xx: List [List[_]]) : List [List[_]] = 
  xx match {
    case aa :: bb :: Nil => 
      aa.map (a => bb.map (b => List (a, b))).flatten       
    case aa :: bb :: cc => 
      xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten
    case _ => xx
}

对于 2 个列表,它是过度设计的。 你虽然可以称它为

   xproduct (List (l, t))

Here is a type-agnostic solution for an unknown, varying number of elements in a unknown number of lists:

def xproduct (xx: List [List[_]]) : List [List[_]] = 
  xx match {
    case aa :: bb :: Nil => 
      aa.map (a => bb.map (b => List (a, b))).flatten       
    case aa :: bb :: cc => 
      xproduct (bb :: cc).map (li => aa.map (a => a :: li)).flatten
    case _ => xx
}

For 2 Lists it is overengineered. You could although call it

   xproduct (List (l, t))
违心° 2024-08-03 21:55:53

显然不是。 当我尝试时出现编译错误。

看起来 for..yield 是一个表达式。 你不能有两个收益,因为这并不是表达式的真正一部分。

如果您想生成多个值,为什么不将它们生成为元组或列表呢?

例如:

for( t <- List(1,2,3); l <- List(-1,-2,-3))
  yield (t, l)

Apparently not. I get a compile error when I try it.

It looks like for .. yield is an expression. You can't have two yields, since that's not really part of the expression.

If you want to yield multiple values, why not yield them as a tuple or a list?

For example:

for( t <- List(1,2,3); l <- List(-1,-2,-3))
  yield (t, l)
偷得浮生 2024-08-03 21:55:53

也许yield不是最好的方法? 也许这里可以使用简单的数组附加。

Maybe yield is not the best way to go? Perhaps simple array appending could be used here.

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