2016-09-15 2 views
1

У меня есть список строк, которые я пытаюсь разделить на отдельные списки последовательно, группировка 4-е вхождение т.е. в этом списке:Список групп по данным вхождения в Scala

val data = List("1", "2", "3", "4", "5", "6", "7", "8") 

должны быть сгруппированы в

val list1 = List("1", "5") 
val list2 = List("2", "6") 
val list3 = List("3", "7") 
val list4 = List("4", "8") 

Я не уверен, если я пытаюсь усложнять это, но единственный способ, которым я могу думать, чтобы первой группе элементов с использованием sliding например:

data.sliding(4,4).toList 

приводит

List(List(1, 2, 3, 4), List(5, 6, 7, 8)) 

, а затем реализовать свой собственный unzip метод, который группа выше, как мой желаемый результат.

Пожалуйста, кто-нибудь может сообщить мне, есть ли более простой способ сделать это?

+0

Было бы замечательно, если бы вы можете подтвердить ожидаемое поведение для списков длиной более 8 элементов .... –

ответ

3

Вы можете использовать .transpose в списке .sliding генерирует:

scala> val data = List("1", "2", "3", "4", "5", "6", "7", "8") 
data: List[String] = List(1, 2, 3, 4, 5, 6, 7, 8) 

scala> data.sliding(4, 4).toList 
res1: List[List[String]] = List(List(1, 2, 3, 4), List(5, 6, 7, 8)) 

scala> data.sliding(4, 4).toList.transpose 
res2: List[List[String]] = List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
0

zip после sliding

scala> val data = List("1", "2", "3", "4", "5", "6", "7", "8") 
data: List[String] = List("1", "2", "3", "4", "5", "6", "7", "8") 

scala> val result = data.sliding(4, 4).toList 
result: List[List[String]] = List(List("1", "2", "3", "4"), List("5", "6", "7", "8")) 

scala> result.transpose 
res7: List[(String, String)] = List(("1", "5"), ("2", "6"), ("3", "7"), ("4", "8")) 
+0

Это будет работать, только если список имеет ровно 8 элементов. –

0

Если кортежи бы в качестве вывода, это довольно опрятно:

val tuples = data zip data.drop(4) 
//> tuples : List[(String, String)] = List((1,5), (2,6), (3,7), (4,8)) 

поворот их в List:

tuples.map{case(a,b) => List(a, b)} 
//> List[List[String]] = List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 

EDIT: Показано что комментарий о только работе с 8 невереном

def pairs[A](xs:List[A], n:Int) = 
(xs zip xs.drop(n)).map{case(a,b) => List(a, b)} 

pairs(List("1","2", "3", "4", "5", "6", "7", "8"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
pairs(List("1","2", "3", "4", "5", "6", "7", "8", "9"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8), List(5, 9)) 

pairs(List("1","2", "3", "4", "5", "6", "7", "8", "9", "10"), 4) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8), List(5, 9), List(6, 10)) 
pairs(List("1","2", "3", "4"), 4) 
// List() 
pairs(List("1","2", "3"), 4) 
// List() 
+0

Этот ответ также требует, чтобы «данные» имели ровно 8 элементов. –

+0

Я понятия не имею, почему вы так говорите, потому что это просто неправда. –

+0

Если у вас есть, например, 'data = (от 1 до 12) .toList' вы вернете' List (List (1,5), List (2,6), List (3,7), List (4,8), List (5,9), ...) '; он не «разделяется на отдельные списки», как в вопросе, потому что ваши результаты пересекаются. Если 'data = (от 1 до 4) .toList', вы возвращаете пустой список. –

2

версии, которая будет работать на любую длину списка:

def groupNth[A](n: Int, list: List[A]): List[List[A]] = { 
    val (firstN, rest) = list.splitAt(n) 
    val groupedRest = if (rest.nonEmpty) groupNth(n, rest) else Nil 
    // null.asInstanceOf[A] is of course cheating, but the value is never used 
    firstN.zipAll(groupedRest, null.asInstanceOf[A], Nil).map { 
    case (h, t) => h :: t 
    } 
} 


println(groupNth(4, Nil)) 
// List() 
println(groupNth(4, List(1, 2, 3))) 
// List(List(1), List(2), List(3)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8))) 
// List(List(1, 5), List(2, 6), List(3, 7), List(4, 8)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8, 9))) 
// List(List(1, 5, 9), List(2, 6), List(3, 7), List(4, 8)) 
println(groupNth(4, List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))) 
// List(List(1, 5, 9), List(2, 6, 10), List(3, 7, 11), List(4, 8, 12))