在特定数量的子列表中划分列表

时间:2010-05-21 18:03:21

标签: list scala functional-programming

我想在“特定数量的”子列表中划分列表。

也就是说,例如,如果我有一个列表List(34, 11, 23, 1, 9, 83, 5)并且预期的子列表数量是3,那么我想要List(List(34, 11), List(23, 1), List(9, 83, 5))

我该怎么做呢?我试过了grouped,但它似乎没有做我想做的事。

PS:这不是一个家庭作业问题。请提供直接的解决方案,而不是一些模糊的建议。

编辑:

要求稍有变化......

给定列表List(34, 11, 23, 1, 9, 83, 5)和子列表数= 3,我希望输出为List(List(34), List(11), List(23, 1, 9, 83, 5))。 (即每个列表1个元素,除了包含所有剩余元素的最后一个列表。)

5 个答案:

答案 0 :(得分:4)

根据您更改的要求,

def splitN[A](list: List[A], n: Int): List[List[A]] =
  if(n == 1) List(list) else List(list.head) :: splitN(list.tail, n - 1)

答案 1 :(得分:2)

这是一个艰难的调用,因为在知道列表的大小之前,您不知道要在每个列表中放入多少元素。如果您 知道列表的大小,则可以使用分组:list.grouped((list.size + 2) / 3).toList。但是,它不会像你那样划分元素。

问题:订单是否重要?如果不需要保留元素的顺序,那么有更好的方法来实现这一点。

答案 2 :(得分:2)

如果您可以容忍调用以获取列表的长度,那么

l.grouped( (l.length+2)/3 ).toList

会产生类似于你想要的东西(如果val l = List(34, 11, 23, 1, 9, 83, 5)那么你会得到List(List(34, 11, 23), List(1, 9, 83), List(5))。但如果你希望在你的列表中大致平均分配,那么你将不得不创建自己的这样做的方法 - 没有一个库函数将列表平均分成n个片段。

如果你想按顺序保存碎片,这样的东西就可以了:

def chopList[T](
  l: List[T], pieces: Int,
  len: Int = -1, done: Int = 0, waiting: List[List[T]]=Nil
): List[List[T]] = {
  if (l isEmpty) waiting.reverse
  else {
    val n = (if (len<0) l.length else len)
    val ls = l.splitAt( (n.toLong*(done+1)/pieces - n.toLong*done/pieces).toInt )
    chopList(ls._2,pieces,n,done+1,ls._1 :: waiting)
  }
}

这恰好会返回您想要的内容:List(List(34, 11), List(23, 1), List(9, 83, 5))

如果您不想询问列表的长度,那么您可以编写一个方法来创建一堆桶并依次删除每个桶中的新项目。

答案 3 :(得分:0)

不知道它可以解决你的问题,但是这里尝试一下(当你的数量超出范围时你会怎么看?)

def group[T](list:List[T], count:Int):List[List[T]] = {
  if (count <= 0 || count >= list.length)
    List(list)
  else {
    val numElm = list.length / count
    def loop(list:List[T], i:Int):List[List[T]] = {
      i match {
        case 0 => List(list) 
        case 1 => List(list)
        case _ =>  {
          val l = list.splitAt(numElm)
          l._1 :: loop(l._2, i-1)
        }
      }
    }
    loop(list, count)
  }
}

答案 4 :(得分:0)

2.8中有grouped新内容吗? 2.7.7的自制解决方案可能如下所示:

def splitTo (li: List [Int], count: Int) : List [List [Int]] = {
    val size = li.length / count

    if (count > 1) li.take (size) :: splitTo (li.drop (size), count-1) else 
        li :: Nil
} 

参数化列表[T]留给读者一个例外。