2010-05-21 70 views
4

我想劃分「特定數量」子列表中的列表。在特定數量的子列表中劃分列表

也就是說,例如,如果我有一個列表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個元素)。

回答

2

這是一個艱難的調用,因爲在知道列表大小之前,不知道要將多少個元素放入每個列表中。如果你知道列表的大小,你可以使用分組:list.grouped((list.size + 2)/3).toList。不過,它不會像你那樣分割元素。

問題:命令是否重要?如果不需要保存元素的順序,那麼有更好的方法來完成這一點。

1

如果你能忍受一個調用來獲取列表的長度,然後

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))

如果你不想問清單的長度,那麼你可以編寫一個方法來創建一堆桶並依次放入一個新的物品。

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) 
    } 
} 
0

grouped是新的2.8嗎?爲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]留作excecise給讀者。

+0

是,'grouped'是在斯卡拉2.8集合庫新。 – 2010-05-22 19:35:34

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)