2014-10-01 91 views
3

假设我给定项的列表:分区给定的总的分区和分区数的列表

[A,B,C,d,E,F,G,H,I,J]

我要求这些分成3所列出,并采取第二列表:

[A,B,C,d] [E,F,G] [H,I ,J]

我该怎么做?

我使用涉及totalPartitionspartitionNumber的模运算的计算思维的功能将类似于

public List<Item> SplitItems(
    List<Item> items, 
    int totalPartitions, 
    int partitionNumber) { } 

我能够获取列表如果partitionNumber为1(第一组) ,但我有问题获得partitionNumber 2及以上的名单。


@Blorgbeard:这是我到目前为止的代码。再次,我只能够处理的第一个分区:

int itemsCount = items.Count; 
int setCount = itemsCount/totalPartitions + ((itemsCount%totalPartitions >= partitionNumber) ? 1 : 0); 
return webItems.Take(setCount).ToList(); 
+2

有多余项目时分割的规则是什么?总是在第一个分区?拆分第一个分区?您将10个项目拆分为3个小组,这些小组不会中断... – 2014-10-01 19:45:13

+0

^您知道规则定义完好后,您可以轻松计算所需子列表的起始索引和结束索引,并使用Skip(跳过)和'拿'来获得该子列表。 – SimpleVar 2014-10-01 19:46:03

+0

@ReedCopsey如果我有10个项目分成3组,那将是[1-4],[5-7],[8-10]。如果我有11个项目,那么它会是[1-4],[5-8],[9-11] – Katie 2014-10-01 19:50:35

回答

3
int smallPartitionSize = list.Count/totalPartitions; 
int remainder = list.Count % totalPartitions; 
int selectedPartitionSize = smallPartitionSize + (partitionNumber <= remainder) ? 1 : 0; 
var start = (partitionNumber - 1) * smallPartitionSize + Math.Min(remainder, partitionNumber - 1); 
return list.Skip(start).Take(selectedPartitionSize); 
+0

这不处理“额外”项 - 请注意该示例将“D”放在分区1中...... – 2014-10-01 19:49:32

+0

谢谢,我没有注意到这一点,我更新了我的答案。 – 2014-10-01 20:09:51

+0

这对我来说不适用于'SplitItems ([10 items],3,1)'和'SplitItems([11 items],3,2)' – Katie 2014-10-01 20:16:16

-1
public static List<T> SplitItems<T>(
    List<T> items, 
    int totalPartitions, 
    int partitionNumber) 
{ 
    var result = new List<T>(); 
    int partitionIndex = partitionNumber - 1; 
    int size = (int)Math.Ceiling((double)items.Count/totalPartitions); 
    result.AddRange(items.Skip(size * partitionIndex).Take(size)); 
    return result; 
} 
2

另一种方法是创建均匀分布的数字0-2的集合,Zip它与你的项目:

var items = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" }; 
var n = items.Length; 

var partitioner = Enumerable.Range(0, n).Select (e => (e * 3)/n); 
// Values: { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2 } 

var result = partitioner.Zip(items, (i,s) => new {i,s}) 
         .Where(z => z.i == 1).Select(z => z.s).ToList(); 
+1

This is interesting approach。但是,我不能使用它,因为它使用'.Zip',我只使用'.net 3.5'。非常酷,但! – Katie 2014-10-01 20:36:00

+1

啊,是的,我错过了在.Net 3.5中编写自己的'Zip'扩展方法应该不会太难,无论如何,我想我也会选择一个开箱即用的解决方案。 – 2014-10-01 20:40:03