在Scala中按给定出现的组列表

时间:2016-09-15 10:08:29

标签: list scala unzip sliding

我有一个字符串列表,我试图按顺序拆分成单独的列表,将第4个字符串分组,即此列表:

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方法,将上面的组合作为我想要的输出。

如果有更简单的方法,有人可以告诉我吗?

4 个答案:

答案 0 :(得分: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))

答案 1 :(得分: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))

答案 2 :(得分: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"))

答案 3 :(得分: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))

编辑:显示仅使用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()