Scala - можно ли использовать yield несколько раз с циклом for? - PullRequest
17 голосов
/ 17 июля 2009

Пример:

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

Могу ли я сделать что-то подобное?

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

В основном я хочу получить несколько результатов для каждой итерации.

Ответы [ 6 ]

22 голосов
/ 17 июля 2009

Непонятно, о чем вы просите - чего вы ожидаете от семантики множественного выхода. Одна вещь, однако, состоит в том, что вы, вероятно, никогда не захотите использовать индексы для навигации по списку - каждый вызов 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)
5 голосов
/ 17 июля 2009

Нет, вы не можете использовать несколько предложений доходности, но есть обходные пути. Например:

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

Конечно, вы можете вкладывать-для понимания, но это приведет к списку элементов, которые, я не верю, вам нужны.

2 голосов
/ 10 апреля 2012

Урожай может быть вложенным, что приведет к ...

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)

Уплощенный раствор семантически отличается.

1 голос
/ 03 марта 2011

Вот решение, не зависящее от типа, для неизвестного, различного числа элементов в неизвестном количестве списков:

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))
0 голосов
/ 17 июля 2009

Может быть доходность не лучший путь? Возможно, здесь можно использовать простое добавление массива.

0 голосов
/ 17 июля 2009

Видимо нет. Я получаю ошибку компиляции, когда я пытаюсь это сделать.

Похоже на ... yield - это выражение. У вас не может быть двух выходов, так как это не является частью выражения.

Если вы хотите получить несколько значений, почему бы не выдать их в виде кортежа или списка?

Например:

for( t <- List(1,2,3); l <- List(-1,-2,-3))
  yield (t, l)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...