Как сгладить Список разных типов в Scala? - PullRequest
11 голосов
/ 15 ноября 2009

У меня есть 4 элемента: List[List[Object]] (объекты различны в каждом элементе), которые я хочу сжать, чтобы получить List[List[obj1],List[obj2],List[obj3],List[obj4]]

Я попытался сжать их, и получил вложенный список, к которому не могу применить flatten, потому что он говорит: нет неявного аргумента, соответствующего типу параметра.

Как я могу решить это? я должен попробовать другой способ, или есть ли способ заставить сгладить работу?

Я немного новичок в скале, так что это может быть глупый вопрос: D Заранее спасибо! Clau

Ответы [ 7 ]

21 голосов
/ 16 апреля 2013

для одного вложенного списка : flatten сделает:

scala> List(List(1), List(2), List(3)).flatten
res4: List[Int] = List(1, 2, 3)

scala> List(List(List(1)), List(List(2)), List(List(3))).flatten
res5: List[List[Int]] = List(List(1), List(2), List(3))

Для нескольких вложенных списков тогда вы можете:

def flatten(ls: List[Any]): List[Any] = ls flatMap {
  case i: List[_] => flatten(i)
  case e => List(e)
}

val k = List(1, List(2, 3), List(List(List(List(4)), List(5)), List(6, 7)), 8)
flatten(k)

печатает List[Any] = List(1, 2, 3, 4, 5, 6, 7, 8)

14 голосов
/ 15 ноября 2009

До Scala 2.9

Из вставленной ошибки похоже, что вы пытаетесь вызвать flatten метод экземпляра самого вложенного списка. Для этого требуется неявное преобразование для создания чего-либо типа Iterable из любых типов, содержащихся в списке. В вашем случае похоже, что компилятор не может его найти.

Используйте flatten из одноэлементного объекта List, для которого не требуется этот неявный параметр:

scala> val foo = List(List(1), List("a"), List(2.3))
foo: List[List[Any]] = List(List(1), List(a), List(2.3))

scala> List.flatten(foo)
res1: List[Any] = List(1, a, 2.3)

После Scala 2.9

Просто используйте foo.flatten.

4 голосов
/ 16 ноября 2009

Вопрос очень расплывчатый. Вы должны просто вставить то, что у вас есть, вместо того, чтобы пытаться описать это. Это сделало бы жизнь каждого (включая вашу) намного проще.

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

scala> List(List(1))
res0: List[List[Int]] = List(List(1))

scala> List(List(2))
res1: List[List[Int]] = List(List(2))

scala> List(List(3))
res2: List[List[Int]] = List(List(3))

scala> List(List(4))
res3: List[List[Int]] = List(List(4))

scala> res0 ::: res1 ::: res2 ::: res3
res4: List[List[Int]] = List(List(1), List(2), List(3), List(4))
2 голосов
/ 14 октября 2013

В скале 2.10.2

scala> val foo = List(List(1), List("a"), List(2.3))
foo: List[List[Any]] = List(List(1), List(a), List(2.3))

scala> foo.flatten
res0: List[Any] = List(1, 2, a, 2.3)

работает нормально, но

если вы бежите как

scala>  val foo = List(List(1,2), 2, List(2.3))
foo: List[Any] = List(List(1, 2), 2, List(2.3))

scala> foo.flatten
<console>:9: error: No implicit view available from Any => scala.collection.GenTraversableOnce[B].
              foo.flatten

для этого я пишу функцию

scala> def flat(ls: List[Any]): List[Any]= ls flatten {
     |   case t: List[Any] =>  flat(t)
     |   case c => List(c)
     | }   
flat: (ls: List[Any])List[Any]

scala> flat(List(List(1,2),2,List(2.3)))
res2: List[Any] = List(1, 2, 2, 2.3)
1 голос
/ 15 ноября 2009

Одновременно можно сжать только два списка с помощью list1 zip list2, а сигнатура типа для возвращаемых значений - List[(A,B)], а не List[List[obj1],List[obj2],List[obj3],List[obj4]]

1 голос
/ 15 ноября 2009

Это помогает, если у нас есть пример. Ваш код должен выглядеть примерно так:

val f = List(1, 2)
val s = List(3, 4)
val top = List(f, s)

List.flatten(top) // returns List(1, 2, 3, 4)
0 голосов
/ 12 августа 2016

Рассмотрим List.concat, например

List.concat(List(1), List(2,22), List(3))    // delivers List(1, 2, 22, 3)
...