在x个较小的列表之间均匀地拆分项目列表

Loy*_*lar 1 c# linq list

我再次问这个问题,因为我上一次问它,它被错误地标记为重复.我这次将包含更多信息,这可能使我更容易理解我的需要(由于没有正确定义问题,这可能是我自己的错).

我正在尝试将通用类型的列表拆分为4个列表.为了简单和理解,我将在这个例子中使用一个整数列表,但这不应该有所作为.

我做了很多搜索,发现了多个答案,比如"使用LINQ将列表拆分为子列表",使用批处理方法进行拆分,我尝试了MoreLinq的Batch方法等等.这些建议适用于他们应该做的事情,但它们并不像我需要的那样工作.

如果我有一个包含以下元素的列表(整数范围1-25):

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] 
Run Code Online (Sandbox Code Playgroud)

然后我需要做的是制作4个列表,其中包含可变数量的元素,其中元素在同一列表中递增,而不是跳转到下一个列表与下一个元素.

[ 1,  2,  3,  4,  5,  6,  7]
[ 8,  9, 10, 11, 12, 13, 14]
[15, 16, 17, 18, 19, 20, 21]
[20, 21, 22, 23, 24, 25]
Run Code Online (Sandbox Code Playgroud)

当在链接的任何一个问题中使用解决方案时,以4"部分"作为参数,我得到这样的列表(这是元素跳转到下一个列表而不是列表的下一个元素的示例):

[1, 5,  9, 13, 17, 21, 25],
[2, 6, 10, 14, 18, 22, 26],
[3, 7, 11, 15, 19, 23, 27],
[4, 8, 12, 16, 20, 24]
Run Code Online (Sandbox Code Playgroud)

或者这个(和MoreLinq的Batch方法一样)

[ 1,  2,  3,  4],
[ 5,  6,  7,  8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24],
[25, 26, 27],
Run Code Online (Sandbox Code Playgroud)

因此,第一个解决方案将列表拆分为4个列表,但是将元素放入错误的顺序.第二种解决方案按正确的顺序拆分列表,但不是正确的长度.在最后一个解决方案中,他获得了X个列表,每个列表中包含4个元素,其中我需要有4个列表,每个列表中包含X个元素.

Ser*_*kiy 9

您可以使用以下扩展方法在所需数量的子列表上拆分列表,并在第一个子列表中包含其他项:

public static IEnumerable<List<T>> Split<T>(this List<T> source, int count)
{
    int rangeSize = source.Count / count;
    int firstRangeSize = rangeSize + source.Count % count;
    int index = 0;

    yield return source.GetRange(index, firstRangeSize);
    index += firstRangeSize;

    while (index < source.Count)
    {         
        yield return source.GetRange(index, rangeSize);
        index += rangeSize;
    }
}
Run Code Online (Sandbox Code Playgroud)

给定输入

var list = Enumerable.Range(1, 25).ToList();
var result = list.Split(4);
Run Code Online (Sandbox Code Playgroud)

结果是

[
  [ 1, 2, 3, 4, 5, 6, 7 ],
  [ 8, 9, 10, 11, 12, 13 ],
  [ 14, 15, 16, 17, 18, 19 ],
  [ 20, 21, 22, 23, 24, 25 ]
]
Run Code Online (Sandbox Code Playgroud)

更新:此解决方案为每个范围添加了额外的项目

public static IEnumerable<List<T>> Split<T>(this List<T> source, int count)
{
    int rangeSize = source.Count / count;
    int additionalItems = source.Count % count;
    int index = 0;

    while (index < source.Count)
    {   
        int currentRangeSize = rangeSize + ((additionalItems > 0) ? 1 : 0);
        yield return source.GetRange(index, currentRangeSize);
        index += currentRangeSize;
        additionalItems--;
    }
}
Run Code Online (Sandbox Code Playgroud)