Grouping lists into groups of X items per group

后端 未结 5 745
一个人的身影
一个人的身影 2020-12-09 22:54

I\'m having a problem knowing the best way to make a method to group a list of items into groups of (for example) no more than 3 items. I\'ve created the method below, but w

5条回答
  •  既然无缘
    2020-12-09 23:35

    .net Fiddle

    Essentially you have an IEnumerable, and you want to group it into an IEnumerable of IGroupables which each contain the key as an index and the group as the values. Your version does seem to accomplish on the first pass, but I think that you can definitely stream line a little bit.

    Using skip and take is the most desirable way to accomplish in my opinion, but the custom key for grouping is where there is an issue. There is a way around this which is to create your own class as a grouping template (seen in this answer: https://stackoverflow.com/a/5073144/1026459).

    The end result is this:

    public static class GroupExtension
    {
        public static IEnumerable> GroupAt(this IEnumerable source, int itemsPerGroup)
        {
            for(int i = 0; i < (int)Math.Ceiling( (double)source.Count() / itemsPerGroup ); i++)
            {
                var currentGroup = new Grouping{ Key = i };
                currentGroup.AddRange(source.Skip(itemsPerGroup*i).Take(itemsPerGroup));
                yield return currentGroup;
            }
        }
        private class Grouping : List, IGrouping
        {
            public TKey Key { get; set; }
        }
    }
    

    And here is the demo in the fiddle which consumes it on a simple string

    public class Program
    {
        public void Main(){
            foreach(var p in getLine().Select(s => s).GroupAt(3))
                Console.WriteLine(p.Aggregate("",(s,val) => s += val));
        }
        public string getLine(){ return "Hello World, how are you doing, this just some text to show how the grouping works"; }
    }
    

    edit

    Alternatively as just an IEnumerable of IEnumerable

    public static IEnumerable> GroupAt(this IEnumerable source, int itemsPerGroup)
    {
        for(int i = 0; i < (int)Math.Ceiling( (double)source.Count() / itemsPerGroup ); i++)
            yield return source.Skip(itemsPerGroup*i).Take(itemsPerGroup);
    }
    

提交回复
热议问题