Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在x个较小的列表之间平均拆分项目列表_C#_Linq_List - Fatal编程技术网

C# 在x个较小的列表之间平均拆分项目列表

C# 在x个较小的列表之间平均拆分项目列表,c#,linq,list,C#,Linq,List,我再次问这个问题,自从上次我问它以来,它被错误地标记为重复。这次我将提供更多的信息,这可能会使我更容易理解我的需求(这很可能是我自己没有正确定义问题的过错) 我正在尝试将一个泛型类型的列表拆分为4个列表。为了简单易懂,我将在本例中使用整数列表,但这不会有什么区别 我做了很多搜索,找到了很多答案,比如,我尝试了MoreLinq的批处理方法等等。这些建议很好地完成了它们应该做的事情,但它们没有按照我需要的方式工作 如果我有一个包含以下元素的列表(整数范围为1-25): 然后我需要做的是创建4个列表,

我再次问这个问题,自从上次我问它以来,它被错误地标记为重复。这次我将提供更多的信息,这可能会使我更容易理解我的需求(这很可能是我自己没有正确定义问题的过错)

我正在尝试将一个泛型类型的列表拆分为4个列表。为了简单易懂,我将在本例中使用整数列表,但这不会有什么区别

我做了很多搜索,找到了很多答案,比如,我尝试了MoreLinq的批处理方法等等。这些建议很好地完成了它们应该做的事情,但它们没有按照我需要的方式工作

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

然后我需要做的是创建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]
当使用任何一个链接问题的答案时,以4个“部分”作为参数,我得到如下列表(这是一个示例,其中元素跳转到下一个列表,而不仅仅是列表中的下一个元素):

或者这个(与MoreLinq的批处理方法相同)


因此,第一个解决方案将列表拆分为4个列表,但将元素按错误的顺序排列。第二种解决方案按正确的顺序拆分列表,但长度不正确。在上一个解决方案中,他得到了X个列表,每个列表中有4个元素,其中我需要有4个列表,每个列表中有X个元素

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

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;
    }
}
结果是

[
  [ 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 ]
]
更新:此解决方案向每个范围添加其他项

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--;
    }
}
公共静态IEnumerable拆分(此列表源,整数计数)
{
int rangeSize=源。计数/计数;
int additionalItems=source.Count%Count;
int指数=0;
while(索引0)?1:0);
收益返回源.GetRange(索引,currentRangeSize);
索引+=当前范围大小;
其他项目--;
}
}

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

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;
    }
}
结果是

[
  [ 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 ]
]
更新:此解决方案向每个范围添加其他项

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--;
    }
}
公共静态IEnumerable拆分(此列表源,整数计数)
{
int rangeSize=源。计数/计数;
int additionalItems=source.Count%Count;
int指数=0;
while(索引0)?1:0);
收益返回源.GetRange(索引,currentRangeSize);
索引+=当前范围大小;
其他项目--;
}
}
它首先引入了一个计数器(
currentGroupIndex
),该计数器从零开始,将为列表中的每个元素递增。当组大小达到时,索引将重置为零。
变量
step1
现在包含包含
属性的项。
然后在
GroupBy
语句中使用
Group

它首先引入了一个计数器(
currentGroupIndex
),该计数器从零开始,将为列表中的每个元素递增。当组大小达到时,索引将重置为零。
变量
step1
现在包含包含
属性的项。

然后在
GroupBy
语句中使用
Group
值。

这里是另一个基于
IEnumerable
的解决方案。它具有以下特点:

  • 始终生成
    batchCount
    项,如果源可枚举项小于批大小,则将生成空列表
  • 偏爱前面较大的列表(例如,当batchCount为2且大小为3时,结果的长度将为[2,1]
  • 多次迭代IEnumerable。这意味着,若在此处执行实体框架查询之类的操作,则应在某处调用AsEnumerable
第一个示例针对
List

公共静态类批处理操作
{
公共静态IEnumerable批处理(此列表项,int batchCount)
{
int totalSize=items.Count;
int剩余=总大小%batchCount;
int skip=0;
对于(int i=0;iint size=totalSize/batchCount+(i这里是另一个基于
IEnumerable
的解决方案。它具有以下特点:

  • 始终生成
    batchCount
    项,如果源可枚举项小于批大小,则将生成空列表
  • 偏爱前面较大的列表(例如,当batchCount为2且大小为3时,结果的长度将为[2,1]
  • 多次迭代IEnumerable。这意味着,若在此处执行实体框架查询之类的操作,则应在某处调用AsEnumerable
第一个示例针对
List

公共静态类批处理操作
{
公共静态IEnumerable批处理(此列表项,int batchCount)
{
int totalSize=items.Count;
整数=总
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--;
    }
}
        const int groupSize = 4;

        var items = new []{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};

        var currentGroupIndex=-1;

        var step1 = items.Select(a =>{
            if (++currentGroupIndex >= groupSize)
                currentGroupIndex = 0;
            return new {Group = currentGroupIndex, Value = a};
        }).ToArray();


        var step2 = step1.GroupBy(a => a.Group).Select(a => a.ToArray()).ToArray();

        var group1 = step2[0].Select(a => a.Value).ToArray();
        var group2 = step2[1].Select(a => a.Value).ToArray();
        var group3 = step2[2].Select(a => a.Value).ToArray();
        var group4 = step2[3].Select(a => a.Value).ToArray();
public static class BatchOperations
{
    public static IEnumerable<List<T>> Batch<T>(this List<T> items, int batchCount)
    {
        int totalSize = items.Count;
        int remain = totalSize % batchCount;
        int skip = 0;
        for (int i = 0; i < batchCount; i++)
        {
            int size = totalSize / batchCount + (i <= remain ? 1 : 0);
            if (skip + size > items.Count) yield return new List<T>(0);
            else yield return items.GetRange(skip, size);
            skip += size;
        }
    }

    public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items, int batchCount)
    {
        int totalSize = items.Count();
        int remain = totalSize%batchCount;
        int skip = 0;
        for (int i = 0; i < batchCount; i++)
        {
            int size = totalSize/batchCount + (i <= remain ? 1 : 0);
            yield return items.Skip(skip).Take(size);
            skip += size;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    public static class EnumerableExt
    {
        public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> input, int blockCount, int count)
        {
            int blockSize = count/blockCount;
            int currentBlockSize = blockSize + count%blockSize;

            var enumerator = input.GetEnumerator();

            while (enumerator.MoveNext())
            {
                yield return nextPartition(enumerator, currentBlockSize);
                currentBlockSize = blockSize;
            }
        }

        private static IEnumerable<T> nextPartition<T>(IEnumerator<T> enumerator, int blockSize)
        {
            do
            {
                yield return enumerator.Current;
            }
            while (--blockSize > 0 && enumerator.MoveNext());
        }
    }

    class Program
    {
        private void run()
        {
            var list = Enumerable.Range(1, 25).ToList();
            var sublists = list.Partition(4, list.Count);

            foreach (var sublist in sublists)
                Console.WriteLine(string.Join(" ", sublist.Select(element => element.ToString())));
        }

        static void Main()
        {
            new Program().run();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Splitter
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> numbers = Enumerable.Range(1, 25).ToList();
            int groupCount = 4;

            var lists = numbers.Groupem(groupCount, (e, i) =>
            {
                // In what group do i wanna have this element.
                int divider = numbers.Count / groupCount;
                int overflow = numbers.Count % divider;
                int index = (i - overflow) / divider;
                return index < 0 ? 0 : index;
            });

            Console.WriteLine("numbers: {0}", numbers.ShowContent());

            Console.WriteLine("Parts");
            foreach (IEnumerable<int> list in lists)
            {
                Console.WriteLine("{0}", list.ShowContent());
            }
        }
    }

    public static class EnumerableExtensions
    {
        private static List<T>[] CreateGroups<T>(int size)
        {
            List<T>[] groups = new List<T>[size];

            for (int i = 0; i < groups.Length; i++)
            {
                groups[i] = new List<T>();
            }

            return groups;
        }

        public static void Each<T>(this IEnumerable<T> source, Action<T, int> action)
        {
            var i = 0;
            foreach (var e in source) action(e, i++);
        }

        public static IEnumerable<IEnumerable<T>> Groupem<T>(this IEnumerable<T> source, int groupCount, Func<T, int, int> groupPicker, bool failOnOutOfBounds = true)
        {
            if (groupCount <= 0) throw new ArgumentOutOfRangeException("groupCount", "groupCount must be a integer greater than zero.");

            List<T>[] groups = CreateGroups<T>(groupCount);

            source.Each((element, index) =>
            {
                int groupIndex = groupPicker(element, index);

                if (groupIndex < 0 || groupIndex >= groups.Length)
                {
                    // When allowing some elements to fall out, set failOnOutOfBounds to false
                    if (failOnOutOfBounds)
                    {
                        throw new Exception("Some better exception than this");
                    }
                }
                else
                {
                    groups[groupIndex].Add(element);
                }
            });

            return groups;
        }

        public static string ShowContent<T>(this IEnumerable<T> list)
        {
            return "[" + string.Join(", ", list) + "]";
        }
    }
}
public static IList<Ilist<T>> Segment<T>(
        this IEnumerable<T> source,
        int segments)
{
    if (segments < 1)
    {
        throw new ArgumentOutOfRangeException("segments");
    }

    var list = source.ToList();
    var result = new IList<T>[segments];

    // In case the source is empty.
    if (!list.Any())
    {
        for (var i = 0; i < segments; i++)
        {
            result[i] = new T[0];
        }

        return result;
    }

    int remainder;
    var segmentSize = Math.DivRem(list.Count, segments, out remainder);
    var postion = 0;
    var segment = 0;
    while (segment < segments)
    {
        var count = segmentSize;
        if (remainder > 0)
        {
            remainder--;
            count++;
        }

        result[segment] = list.GetRange(position, count);
        segment++;
        position += count;
    }

    return result;
}