Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.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
.net 将集合拆分为n个部分不会产生所需的结果安全性_.net_Vb.net_Linq_Ienumerable - Fatal编程技术网

.net 将集合拆分为n个部分不会产生所需的结果安全性

.net 将集合拆分为n个部分不会产生所需的结果安全性,.net,vb.net,linq,ienumerable,.net,Vb.net,Linq,Ienumerable,我正在尝试将一个集合拆分为特定数量的部分,我已经找到了一些关于StackOverflow的帮助解决方案: 这是我从@Hasan Khan solution的VB.Net翻译: ''' <summary> ''' Splits an <see cref="IEnumerable(Of T)"/> into the specified amount of secuences. ''' </summary> Public Shared Function SplitI

我正在尝试将一个集合拆分为特定数量的部分,我已经找到了一些关于StackOverflow的帮助解决方案:

这是我从@Hasan Khan solution的VB.Net翻译:

''' <summary>
''' Splits an <see cref="IEnumerable(Of T)"/> into the specified amount of secuences.
''' </summary>
Public Shared Function SplitIntoParts(Of T)(ByVal col As IEnumerable(Of T),
                                            ByVal amount As Integer) As IEnumerable(Of IEnumerable(Of T))

    Dim i As Integer = 0

    Dim splits As IEnumerable(Of IEnumerable(Of T)) =
                 From item As T In col
                 Group item By item = Threading.Interlocked.Increment(i) Mod amount
                 Into Group
                 Select Group.AsEnumerable()

    Return splits


End Function
''' <summary>
''' Splits an <see cref="IEnumerable(Of T)"/> into the specified amount of secuences.
''' </summary>
Public Shared Function SplitIntoParts(Of T)(ByVal col As IEnumerable(Of T),
                                            ByVal amount As Integer) As IEnumerable(Of IEnumerable(Of T))

    Return col.Select(Function(item, index) New With {index, item}).
               GroupBy(Function(x) x.index Mod amount).
               Select(Function(x) x.Select(Function(y) y.item))

End Function
这两个函数都给出了此结果:

1: { 1, 3, 5, 7, 9 }
2: { 2, 4, 6, 8, 10 }
而不是这些秘密:

1: { 1, 2, 3, 4, 5 } 
2: { 6, 7, 8, 9, 10 }

我做错了什么?

你没有做错什么;只是你使用的方法并没有按照你想要的方式来排序。想想mod和GroupBy是如何工作的,你就会明白为什么了

我建议您使用,因为它保持了您收藏的顺序,我冒昧地将它翻译成VB.Net

您只需事先计算每个分区的大小,因为它不会将集合拆分为n个块,而是拆分为长度为n的块:


请随意隐藏分区CintMath.天花板。。。参与新方法。

你没有做错什么;只是你使用的方法并没有按照你想要的方式来排序。想想mod和GroupBy是如何工作的,你就会明白为什么了

我建议您使用,因为它保持了您收藏的顺序,我冒昧地将它翻译成VB.Net

您只需事先计算每个分区的大小,因为它不会将集合拆分为n个块,而是拆分为长度为n的块:


请随意隐藏分区CintMath.天花板。。。参与新方法。

低效解决方案对数据的迭代次数过多:

class Program
{
    static void Main(string[] args)
    {
        var data = Enumerable.Range(1, 10);
        var result = data.Split(2);            
    }
}

static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> col, int amount)
    {
        var chunkSize = (int)Math.Ceiling((double)col.Count() / (double)amount);

        for (var i = 0; i < amount; ++i)
            yield return col.Skip(chunkSize * i).Take(chunkSize);
    }
}

低效的解决方案数据迭代次数过多:

class Program
{
    static void Main(string[] args)
    {
        var data = Enumerable.Range(1, 10);
        var result = data.Split(2);            
    }
}

static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> col, int amount)
    {
        var chunkSize = (int)Math.Ceiling((double)col.Count() / (double)amount);

        for (var i = 0; i < amount; ++i)
            yield return col.Skip(chunkSize * i).Take(chunkSize);
    }
}

MyExtensions类有两个公共拆分方法:

对于ICollection-仅在集合中迭代一次-用于拆分。 For IEnumerable-遍历可枚举项两次:计数项和拆分项。如果可能的话,不要使用这个。第一个是安全的,速度快两倍。 更重要的是:该算法试图返回指定数量的集合


MyExtensions类有两个公共拆分方法:

对于ICollection-仅在集合中迭代一次-用于拆分。 For IEnumerable-遍历可枚举项两次:计数项和拆分项。如果可能的话,不要使用这个。第一个是安全的,速度快两倍。 更重要的是:该算法试图返回指定数量的集合


我不是LINQ专家。。但是mod在这里是错误的。你会想按某种计数进行分组特别是分区method@Ric谢谢,我已经试过了,但那是为了将集合拆分为若干个元素/秒,我正在尝试将集合拆分为若干个秒。@Sam Axe谢谢你的评论,但是VB.Net中的C%运算符相当于Mod,我不对?是的,Mod相当于%。但是如果你想要一个序列,Mod是错误的操作。我不是LINQ专家。。但是mod在这里是错误的。你会想按某种计数进行分组特别是分区method@Ric谢谢,我已经试过了,但那是为了将集合拆分为若干个元素/秒,我正在尝试将集合拆分为若干个秒。@Sam Axe谢谢你的评论,但是VB.Net中的C%运算符相当于Mod,我不对?是的,Mod相当于%。但是如果你想要一个序列,Mod是一个错误的操作。谢谢你解释了顺序和代码,但是你的函数在每个集合中分裂成若干个元素,而不是分裂成若干个集合,至少我的VB翻译就是这样做的,我错了?@ElektroStudios是的,正如我在回答中所说,该函数将每个集合拆分为若干个元素;因此,您必须计算每个集合中的数字元素,正如我在回答中所说的:CIntMath.CeilingmainCol.Count/amount,这正是Szer在回答中所做的,希望我的解决方案中的函数更有效,因为它不会在源可枚举项上迭代多次。感谢您解释排序和代码,但您的函数会分解为每个集合的多个元素,而不是多个集合,至少我的VB翻译就是这样做的,我错了?@ElektroStudios是的,正如我在回答中所说,该函数将每个集合拆分为若干个元素;因此,您必须计算每个集合中的数字元素,正如我在回答中所说的:CIntMath.CeilingmainCol.Count/amount,这正是Szer在回答中所做的,希望我的解决方案中的函数更有效,因为它不会在源枚举上重复多次。我对该函数有问题,在某种程度上似乎是不完美的,如果我尝试将一个包含10个项目的集合拆分为10个片段,它应该会生成10个包含1个元素的集合,但不会。我正在研究为什么这个方法会迭代IEnumerable col 1+数量次。第一次计算ITME,下一次在for循环的每个迭代中。这是可行的,但不是有效的解决办法。首先,是的
最好拆分ICollection,而不是IEnumerable ICollection具有Count。第二:不可能对每个块都调用Skip。@ElektroStudios我自己测试过,你的新代码一切正常example@rtf_leg是的,你说得对。在我的回答中添加了免责声明我的功能有问题,在某种程度上似乎不完美,如果我尝试将10个项目的集合拆分为10个片段,它应该会生成10个集合,每个集合包含1个元素,但不会。我正在研究为什么这个方法会迭代IEnumerable col 1+数量次。第一次计算ITME,下一次在for循环的每个迭代中。这是可行的,但不是有效的解决办法。首先:最好拆分ICollection,而不是IEnumerable ICollection有Count。第二:不可能对每个块都调用Skip。@ElektroStudios我自己测试过,你的新代码一切正常example@rtf_leg是的,你说得对。在我的回答中添加了免责声明惊人,谢谢,我实际上在处理金额值时执行了一个错误,并且在值不是“collection.Count”的乘数时引发了一个异常。为了避免使用@Szer的解决方案生成空secuences,您的解决方案考虑了该功能。惊人,谢谢,实际上,我在处理amount值时执行了一个错误,并在该值不是“collection.Count”的乘数时引发了一个异常。为了避免使用@Szer的解决方案生成空secuences,您的解决方案考虑了该功能。
mainCol.Partition(CInt(Math.Ceiling(mainCol.Count() / 2)))
class Program
{
    static void Main(string[] args)
    {
        var data = Enumerable.Range(1, 10);
        var result = data.Split(2);            
    }
}

static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> col, int amount)
    {
        var chunkSize = (int)Math.Ceiling((double)col.Count() / (double)amount);

        for (var i = 0; i < amount; ++i)
            yield return col.Skip(chunkSize * i).Take(chunkSize);
    }
}
Public Shared Iterator Function SplitIntoParts(Of T)(ByVal col As IEnumerable(Of T),
                                                     ByVal amount As Integer) As IEnumerable(Of IEnumerable(Of T))

    Dim chunkSize As Integer = CInt(Math.Ceiling(CDbl(col.Count()) / CDbl(amount)))

    For i As Integer = 0 To amount - 1
        Yield col.Skip(chunkSize * i).Take(chunkSize)
    Next

End Function
public static class MyExtensions
{
    // Works with ICollection - iterates through collection only once.
    public static IEnumerable<IEnumerable<T>> Split<T>(this ICollection<T> items, int count)
    {
        return Split(items, items.Count, count);
    }

    // Works with IEnumerable and iterates items TWICE: first for count items, second to split them.
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items, int count)
    {            
        // ReSharper disable PossibleMultipleEnumeration
        var itemsCount = items.Count();
        return Split(items, itemsCount, count);
        // ReSharper restore PossibleMultipleEnumeration
    }

    private static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> items, int itemsCount, int partsCount)
    {
        if (items == null)
            throw new ArgumentNullException("items");
        if (partsCount <= 0)
            throw new ArgumentOutOfRangeException("partsCount");

        var rem = itemsCount % partsCount;
        var min = itemsCount / partsCount;
        var max = rem != 0 ? min + 1 : min;

        var index = 0;
        var enumerator = items.GetEnumerator();

        while (index < itemsCount)
        {
            var size = 0 < rem-- ? max : min;
            yield return SplitPart(enumerator, size);
            index += size;
        }
    }

    private static IEnumerable<T> SplitPart<T>(IEnumerator<T> enumerator, int count)
    {
        for (var i = 0; i < count; i++)
        {
            if (!enumerator.MoveNext())
                break;
            yield return enumerator.Current;
        }            
    }
}
var items = new [] {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};

for(var i = 1; i <= items.Length + 3; i++)
{
    Console.WriteLine("{0} part(s)", i);
    foreach (var part in items.Split(i))
        Console.WriteLine(string.Join(", ", part));
    Console.WriteLine();
}
1 part(s)
a, b, c, d, e, f, g, h, i, j

2 part(s)
a, b, c, d, e
f, g, h, i, j

3 part(s)
a, b, c, d
e, f, g
h, i, j

4 part(s)
a, b, c
d, e, f
g, h
i, j

5 part(s)
a, b
c, d
e, f
g, h
i, j

6 part(s)
a, b
c, d
e, f
g, h
i
j

7 part(s)
a, b
c, d
e, f
g
h
i
j

8 part(s)
a, b
c, d
e
f
g
h
i
j

9 part(s)
a, b
c
d
e
f
g
h
i
j

10 part(s)
a
b
c
d
e
f
g
h
i
j

11 part(s) // Only 10 items in collection.
a
b
c
d
e
f
g
h
i
j

12 part(s) // Only 10 items in collection.
a
b
c
d
e
f
g
h
i
j

13 part(s)  // Only 10 items in collection.
a
b
c
d
e
f
g
h
i
j