Scala - 可以使用for循环多次使用?

时间:2021-01-06 20:21:13

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.

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

6 个解决方案

#1


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.

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

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)

#2


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

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

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.

当然,你可以嵌套for-comprehension,但这会产生一个元素列表列表,我不相信你想要的。

#3


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.

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

#4


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

对于2个列表,它是过度设计的。你可以打电话给它

   xproduct (List (l, t))

#5


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.

它看起来像.. yield是一个表达式。你不能有两个收益率,因为那不是表达式的一部分。

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)

#6


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

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

#1


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.

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

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)

#2


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

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

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.

当然,你可以嵌套for-comprehension,但这会产生一个元素列表列表,我不相信你想要的。

#3


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.

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

#4


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

对于2个列表,它是过度设计的。你可以打电话给它

   xproduct (List (l, t))

#5


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.

它看起来像.. yield是一个表达式。你不能有两个收益率,因为那不是表达式的一部分。

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)

#6


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

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