如何使用LINQ在n个部分中垂直拆分列表

Ale*_*bin 6 c# linq list

我想将一个列表分成几部分,而不知道我将在该列表中有多少项目.问题与那些想要将列表拆分为固定大小的块的人不同.

int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Run Code Online (Sandbox Code Playgroud)

我希望将值垂直分割.

拆分为2:

-------------------
| item 1 | item 6 |
| item 2 | item 7 |
| item 3 | item 8 |
| item 4 | item 9 |
| item 5 |        |
Run Code Online (Sandbox Code Playgroud)

拆分为3:

| item 1 | item 4 | item 7 |
| item 2 | item 5 | item 8 |
| item 3 | item 6 | item 9 |
Run Code Online (Sandbox Code Playgroud)

拆分为4:

| item 1 | item 4 | item 6 | item 8 |
| item 2 | item 5 | item 7 | item 9 |
| item 3 |        |        |        |
Run Code Online (Sandbox Code Playgroud)

我发现了一些可以做到这一点的c#扩展,但它没有按照我想要的方式分配值.这是我发现的:

// this technic is an horizontal distribution
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> list, int parts)
{
    int i = 0;
    var splits = from item in list
                    group item by i++ % parts into part
                    select part.AsEnumerable();
    return splits;
}
Run Code Online (Sandbox Code Playgroud)

结果是这个但我的问题是值是水平分布的:

| item 1 | item 2 |
| item 3 | item 4 |
| item 5 | item 6 |
| item 7 | item 8 |
| item 9 |        |
Run Code Online (Sandbox Code Playgroud)

要么

| item 1 | item 2 | item 3 |
| item 4 | item 5 | item 6 |
| item 7 | item 8 | item 9 |
Run Code Online (Sandbox Code Playgroud)

任何想法如何我可以垂直分配我的价值观,并有可能选择我想要的零件数量

在真实生活中

对于那些想知道我想在哪种情况下垂直拆分列表的人,这里是我网站的一部分截图:

在此输入图像描述

Mar*_*num 15

使用.Take ().Skip(),你可以:

int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

int splitIndex = 4; // or (a.Length / 2) to split in the middle.

var list1 = a.Take(splitIndex).ToArray(); // Returns a specified number of contiguous elements from the start of a sequence.
var list2 = a.Skip(splitIndex).ToArray(); // Bypasses a specified number of elements in a sequence and then returns the remaining elements.
Run Code Online (Sandbox Code Playgroud)

如果你想要,你可以使用.ToList()而不是..ToArray()List<int>


编辑:

在您(稍后澄清)您的问题之后,我想这就是您所需要的:

public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int parts)
    {
        var list = new List<T>(source);
        int defaultSize = (int)((double)list.Count / (double)parts);
        int offset = list.Count % parts;
        int position = 0;

        for (int i = 0; i < parts; i++)
        {
            int size = defaultSize;
            if (i < offset)
                size++; // Just add one to the size (it's enough).

            yield return list.GetRange(position, size);

            // Set the new position after creating a part list, so that it always start with position zero on the first yield return above.
            position += size;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它:

int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var lists = a.Split(2);
Run Code Online (Sandbox Code Playgroud)

这会产生:

分为2: a.Split(2);

| item 1 | item 6 |
| item 2 | item 7 |
| item 3 | item 8 |
| item 4 | item 9 |
| item 5 |        |
Run Code Online (Sandbox Code Playgroud)

拆分为3: a.Split(3);

| item 1 | item 4 | item 7 |
| item 2 | item 5 | item 8 |
| item 3 | item 6 | item 9 |
Run Code Online (Sandbox Code Playgroud)

4分: a.Split(4);

| item 1 | item 4 | item 6 | item 8 |
| item 2 | item 5 | item 7 | item 9 |
| item 3 |        |        |        |
Run Code Online (Sandbox Code Playgroud)

另外,如果你有:

int[] b = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 10 items
Run Code Online (Sandbox Code Playgroud)

分为4: b.Split(4);

| item 1 | item 4 | item 7 | item 9 |
| item 2 | item 5 | item 8 | item 10|
| item 3 | item 6 |        |        |
Run Code Online (Sandbox Code Playgroud)