给定总分区和分区号的列表进行分区

时间:2014-10-01 19:37:59

标签: c# linq .net-3.5

假设我给出了一个项目列表:

  

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

我要求将这些分成3个列表,然后选择第二个列表:

  

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

我该怎么做?

我认为这个功能看起来像是

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

如果partitionNumber为1(第一组),我可以使用涉及totalPartitionspartitionNumber的模运算的计算来获取列表,但我和在获取partitionNumber 2及以上的列表时遇到问题。


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

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

3 个答案:

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

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

答案 2 :(得分:-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;
}