Splitting an array using LINQ

2019-01-25 11:47发布

I have a collection uni-dimensional like this:

[1,2,4,5.....n]

I would like to convert that collection in a bi-dimensional collection like this:

[[1,2,3],
[4,5,6],
...]

Basically I want to group or split if you want, the array in groups of 'n' members

I can do it with a foreach statement, but I am currently learning LINQ so instead of iterating through all elements and create a new array manually I would like to use the LINQ features (if applicable)

Is there any LINQ function to help me to accomplish this??

I was thinking in the GroupBy or SelectMany I do not know if they will help me though but they might

Any help will be truly appreciate it =) :**

6条回答
家丑人穷心不美
2楼-- · 2019-01-25 12:21

It's not a pure LINQ but it's intended to be used with it:

public static class MyEnumerableExtensions
{
    public static IEnumerable<T[]> Split<T>(this IEnumerable<T> source, int size)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source can't be null.");
        }

        if (size == 0)
        {
            throw new ArgumentOutOfRangeException("Chunk size can't be 0.");
        }

        List<T> result = new List<T>(size);
        foreach (T x in source)
        {
            result.Add(x);
            if (result.Count == size)
            {
                yield return result.ToArray();
                result = new List<T>(size);
            }
        }
    }
}

It can be used from your code as:

private void Test()
{
    // Here's your original sequence
    IEnumerable<int> seq = new[] { 1, 2, 3, 4, 5, 6 };

    // Here's the result of splitting into chunks of some length 
    // (here's the chunks length equals 3). 
    // You can manipulate with this sequence further, 
    // like filtering or joining e.t.c.
    var splitted = seq.Split(3);
}
查看更多
虎瘦雄心在
3楼-- · 2019-01-25 12:27

You want Take() and Skip(). These methods will let you split an IEnumerable. Then you can use Concat() to slap them together again.

查看更多
倾城 Initia
4楼-- · 2019-01-25 12:30

It's as simple as:

static class LinqExtensions
{
    public static IEnumerable<IEnumerable<T>> ToPages<T>(this IEnumerable<T> elements, int pageSize)
    {
        if (elements == null)
            throw new ArgumentNullException("elements");
        if (pageSize <= 0)
            throw new ArgumentOutOfRangeException("pageSize","Must be greater than 0!");

        int i = 0;
        var paged = elements.GroupBy(p => i++ / pageSize);
        return paged;
    }
}
查看更多
别忘想泡老子
5楼-- · 2019-01-25 12:31

The sample below will split an array into groups of 4 items each.

int[] items = Enumerable.Range(1, 20).ToArray(); // Generate a test array to split
int[][] groupedItems = items
                         .Select((item, index) => index % 4 == 0 ? items.Skip(index).Take(4).ToArray() : null)
                         .Where(group => group != null)
                         .ToArray();
查看更多
狗以群分
6楼-- · 2019-01-25 12:34

You can group by the index divided by the batch size, like this:

var batchSize = 3;
var batched = orig
    .Select((Value, Index) => new {Value, Index})
    .GroupBy(p => p.Index/batchSize)
    .Select(g => g.Select(p => p.Value).ToList());
查看更多
别忘想泡老子
7楼-- · 2019-01-25 12:41

Use MoreLinq.Batch

 var result = inputArray.Batch(n); // n -> batch size

Example

    var inputs = Enumerable.Range(1,10);

    var output = inputs.Batch(3);


    var outputAsArray = inputs.Batch(3).Select(x=>x.ToArray()).ToArray(); //If require as array
查看更多
登录 后发表回答