2015-03-25 2 views
0

Допустим, мы имеем:Scala частичный список предыдущих элементов

val abc = List(1,2,3,4,5) 

И мы хотим, чтобы произвести список из 5 списков, где каждый ВЗ те включают все предыдущие элементы, включая текущий, как:

//res0: List[List[Int]] = List(List(1), List(1,2), List(1,2,3), List(1,2,3,4), List(1,2,3,4,5)) 

Честно говоря, я пробовал с scanleft, foldLeft и reduceLeft, но не могу найти подходящее решение функции. Я родом из мира Java, и у меня есть проблемы с функциональным мышлением.

Любая помощь будет оценена!

Thx!

ответ

4
val abc = List(1,2,3,4,5) 

val v = abc.scanLeft(List[Int]()){(a, acc)=> a++ List(acc)}.tail 
2

Больше кожуры кошек:

scala> List(1,2,3,4,5).inits.toList.reverse.tail 
res0: List[List[Int]] = List(List(1), List(1, 2), List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5)) 

scala> val is = List(1,2,3,4,5) 
is: List[Int] = List(1, 2, 3, 4, 5) 

scala> ((List.empty[List[Int]], List.empty[Int]) /: is) { 
    | case ((all, cur), i) => val next = cur :+ i ; ((all :+ next, next)) } 
res3: (List[List[Int]], List[Int]) = (List(List(1), List(1, 2), List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5)),List(1, 2, 3, 4, 5)) 

scala> (List(List(is.head)) /: is.tail) { 
    | case (all, i) => all :+ (all.last :+ i) } 
res4: List[List[Int]] = List(List(1), List(1, 2), List(1, 2, 3), List(1, 2, 3, 4), List(1, 2, 3, 4, 5)) 
2

Вот, возможно, неуклюжее решение, которое может быть более очевидным для чтения:

(1 to abc.length).map(abc.take).toList 
+0

Кстати, это гораздо медленнее, чем 'scanLeft вариант. – DaunnC

+1

@DaunnC Почему? Операция ++ является линейной в acc.length, поэтому она будет квадратичной в любом случае. –

+0

Да, вы правы, в Scala была какая-то ошибка или что-то еще на моей машине (нужно больше исследований) в Scala 2.10.3, извините за неполный комментарий. – DaunnC