В Scala можно ли застегивать два списка разных размеров? - PullRequest
14 голосов
/ 24 декабря 2011

Например, предположим, у меня есть

val letters = ('a', 'b', 'c', 'd', 'e')
val numbers = (1, 2)

Можно ли создать список

(('a',1), ('b',2), ('c',1),('d',2),('e',1))

Ответы [ 4 ]

31 голосов
/ 24 декабря 2011

Ваши буквы и цифры являются кортежами, а не списками. Итак, давайте исправим это

scala> val letters = List('a', 'b', 'c', 'd', 'e')
letters: List[Char] = List(a, b, c, d, e)

scala> val numbers = List(1,2)                    
numbers: List[Int] = List(1, 2)

Теперь, если мы их заархивируем, мы не получим желаемого результата

scala> letters zip numbers
res11: List[(Char, Int)] = List((a,1), (b,2))

Но это говорит о том, что если бы числа повторялись бесконечно, то проблема была бы решена

scala> letters zip (Stream continually numbers).flatten
res12: List[(Char, Int)] = List((a,1), (b,2), (c,1), (d,2), (e,1))

К сожалению, это основано на знании того, что цифры короче букв. Так что, чтобы все это исправить

scala> ((Stream continually letters).flatten zip (Stream continually numbers).flatten take (letters.size max numbers.size)).toList
res13: List[(Char, Int)] = List((a,1), (b,2), (c,1), (d,2), (e,1))
7 голосов
/ 24 декабря 2011

Короче списки нужно повторять бесконечно.В этом случае очевидно, что numbers короче, но если вам нужно, чтобы оно работало в целом, вот как вы можете это сделать:

def zipLongest[T](list1 : List[T], list2 : List[T]) : Seq[(T, T)] =
  if (list1.size < list2.size)
    Stream.continually(list1).flatten zip list2
  else
    list1 zip Stream.continually(list2).flatten

val letters = List('a', 'b', 'c', 'd', 'e')
val numbers = List(1, 2)

println(zipLongest(letters, numbers))
1 голос
/ 24 декабря 2015

Вы могли бы сделать простой вкладыш, используя метод map

val letters = List('a', 'b', 'c', 'd', 'e')
val numbers = List(1, 2)

val longZip1 = letters.zipWithIndex.map( x => (x._1, numbers(x._2 % numbers.length)) )

//or, using a for loop
//for (x <- letters.zipWithIndex) yield (x._1, numbers(x._2 % numbers.size))
0 голосов
/ 18 марта 2016

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

val result = (0 to (Math.max(list1.size, list2.size) - 1)) map { index =>  
(list1.lift(index).getOrElse(valWhen1Empty),list2.lift(index).getOrElse(valWhen2Empty))
}

Я сомневаюсь, что это будет хорошо работать с бесконечными списками или потоками, конечно ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...