拆分集合为n个部分使用LINQ,在VB.Net [英] Split a collection into n parts with LINQ, in VB.Net

查看:165
本文介绍了拆分集合为n个部分使用LINQ,在VB.Net的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

在VB.Net,如果我有一个集合是这样的:

 昏暗的收集为IEnumerable(整数)= Enumerable.Range(0,99)
 

我怎么能在小组把它分解/元素的indeterminated量Ienumerables?


条件

使用的 LINQ 查询(而不是 MORELinq 或任何其他第三方库)

不是书面方式一功能,只使用(或追加到集合),一个 LINQ 查询避免了自定义的插入和通用过程分成部分。

不产生匿名键入(因为我会尊重VB.Net 选项声明)。


研究

我读过这些问题,但我没能正确地翻译C# LINQ querys到VB.Net(甚至是在线翻译失败,需要多大的改动):

拆分集合为n个部分的LINQ?

<一个href="http://stackoverflow.com/questions/1349491/how-can-i-split-an-ienumerablestring-into-groups-of-ienumerablestring">How我可以分裂一个IEnumerable&LT;字符串&GT;到了IEnumerable&LT组;串&GT;

拆分表到子列表与LINQ

拆分实体集合为n个部分

这些都是我试着从这些所以给出的解决方案,以适应两种不同途径的几点思考上述问题,但我的翻译不工作,第一不能编译,因为条件的集团通过第二不产生分裂集合,它生成每个每个元素的集合:

1。

 昏暗部分作为整数= 4
    昏暗我作为整数= 0

    昏暗拆分为IEnumerable(中的IEnumerable中(整数))=
        从项目作为整数集合
        集团通过(Math.Max​​(Interlocked.Increment(我),我 -  1)模件)
        走进集团
        选择Group.AsEnumerable
 

2。

 昏暗部分作为整数= 4

    昏暗的结果为IEnumerable(中的IEnumerable中(整数))=
        collection.Select(功能(S,I)新增功能
            {
                主要.value的= S,
                主要.Index = I
            }
        ).GroupBy(功能(项目)
                      返程(item.Index&GT; =(item.Index /件))和(item.Index&GT; = item.Value)
                  端功能,
               功能(项目)item.Value).Cast(中的IEnumerable中(整数))()
 

预期结果

所以,如果我有一个源集合是这样的:

 昏暗的收集为IEnumerable(整数)= {1,2,3,4,5,6,7,8,9,10}
 

和假设我有一个假想的LINQ查询,可以拆分成一个名为可变分割通过变量部分指定的值

 暗淡的部分作为整数= ...
昏暗拆分为IEnumerable(中的IEnumerable中(整数))=
   从价值作为整数集(LINQ查询,简单地将通过给定的'零件'值)
 

如果我choosen了部分值为 4 那么结果将是一个I 可枚举(中IEnumerable的(中整数))这将包含 3 的集合,其中:

 拆分(0)= {1,2,3,4}
拆分(1)= {5,6,7,8}
分割(2)= {9,10}
 

如果我choosen了部分值为 5 那么结果将是一个I 可枚举(中IEnumerable的(中整数))这将包含 2 的集合,其中:

 拆分(0)= {1,2,3,4,5}
拆分(1)= {6,7,8,9,10}
 

如果我choosen了部分值为 1 那么结果将是一个I 可枚举(中IEnumerable的(中整数))这将包含相同的源集合,因为我选择去分割,在短短的 1 部分:

分裂(0)= {1,2,3,4,5,6,7,8,9,10}
 

如果我choosen了部分值为 10 那么结果将是一个I 可枚举(中IEnumerable的(中整数))这将包含 10 的集合,每个源的例子集合的每个值一个集合:

 拆分(0)= {1}
拆分(1)= {2}
分割(2)= {3}
等等...
 

解决方案

您可以使用的范围,的跳过和的,以实现自己的目标。

昏暗的收集为IEnumerable(整数)= {1,2,3,4,5,6,7,8 ,9,10} 昏暗的部分作为整数= 4 昏暗的计数为整数= CINT(Math.Ceiling(collection.Count()/份))= 3 昏暗的结果为IEnumerable(中的IEnumerable中(整数))=无

 方法1:
结果=从我在Enumerable.Range(0,计数)选择collection.Skip(I *部分)。取(部分)
 

 方法2:
结果= Enumerable.Range(0,计数)。选择(功能(我)collection.Skip(I *部分)。取(地区))
 

 对于每个项目的结果
    的Debug.WriteLine(的string.join(,项目))
下一个
 

  

1,2,3,4
  5,6,7,8
  9,10

强制性扩展方法:

 公共模块扩展

    &其中; System.Runtime.CompilerServices.Extension()&GT;
    公共功能斯普利特(TSource中)(集合为IEnumerable(中TSource),BYVAL部分为整数)为IEnumerable(中IEnumerable的TSource中())
        如果(Collection是没有)再抛新ArgumentNullException(集合)
        如果(份&lt; 1),然后抛出新的ArgumentOutOfRangeException(部件)
        昏暗的计数为整数= collection.Count()
        如果(计数= 0),然后返回{}
        如果(部件&GT; =计数),然后返回{}收藏
        返回Enumerable.Range(0,CINT(Math.Ceiling(计数/件))),选择(功能(我)collection.Skip(I *部分)。取(地区))
    端功能

前端模块
 

 的结果= collection.Split(4)
 

Question

In VB.Net, If I have a collection like this:

Dim collection As IEnumerable(Of Integer) = Enumerable.Range(0, 99)

How I could split it in groups/Ienumerables of an indeterminated amount of elements?


Conditions

Using a LINQ query (not MORELinq or any other 3rd party libs)

Not writting a Function, just using (or appending to the collection) a LINQ query avoiding the insertion of a custom and generic procedure to split in parts.

Not generating an Anonymous Type (because I will respect the VB.Net Option Statements).


Research

I've read at these questions but I was not able to properly translate the C# LINQ querys into VB.Net (even online translators fails and need much modifications):

Split a collection into n parts with LINQ?

How can I split an IEnumerable<String> into groups of IEnumerable<string>

Split List into Sublists with LINQ

Split a entity collection into n parts

These are two different approachs that I've tried to adapt from the solutions given in those S.O. questions above, but my translations doesn't works, the first can't compile because the condition of Group By and the second does not generates an splitted collection, it generates a collection per each element:

1.

    Dim parts As Integer = 4
    Dim i As Integer = 0

    Dim splits As IEnumerable(Of IEnumerable(Of Integer)) =
        From item As Integer In collection
        Group By (Math.Max(Interlocked.Increment(i), i - 1) Mod parts)
        Into Group
        Select Group.AsEnumerable

2.

    Dim parts As Integer = 4

    Dim result As IEnumerable(Of IEnumerable(Of Integer)) =
        collection.Select(Function(s, i) New With
            {
                Key .Value = s,
                Key .Index = i
            }
        ).GroupBy(Function(item)
                      Return (item.Index >= (item.Index / parts)) And (item.Index >= item.Value)
                  End Function,
               Function(item) item.Value).Cast(Of IEnumerable(Of Integer))()

Expected Results

So, If I have a source collection like this:

Dim collection As IEnumerable(Of Integer) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

And supposing that I have that imaginary LINQ query that can split into a variable named splits by the value specified on variable parts:

Dim parts as Integer = ...
Dim splits As IEnumerable(Of IEnumerable(Of Integer)) =
   From value As Integer In collection (Linq Query that splits by given 'parts' value)

If I choosen that parts value is 4 then the result will be an IEnumerable(Of IEnumerable(Of Integer)) which will contains 3 collections, where:

splits(0) = {1, 2, 3, 4}
splits(1) = {5, 6, 7, 8}
splits(2) = {9, 10}

If I choosen that parts value is 5 then the result will be an IEnumerable(Of IEnumerable(Of Integer)) which will contains 2 collections, where:

splits(0) = {1, 2, 3, 4, 5}
splits(1) = {6, 7, 8, 9, 10}

If I choosen that parts value is 1 then the result will be an IEnumerable(Of IEnumerable(Of Integer)) which will contains the identical source collection because I choosen to split in just 1 part:

splits(0) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

If I choosen that parts value is 10 then the result will be an IEnumerable(Of IEnumerable(Of Integer)) which will contains 10 collections, one collection per each value of the source example collection:

splits(0) = {1}
splits(1) = {2}
splits(2) = {3}
and so on...

解决方案

You can use Range, Skip and Take to achieve your goal.

Dim collection As IEnumerable(Of Integer) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Dim parts As Integer = 4
Dim count As Integer = CInt(Math.Ceiling(collection.Count() / parts)) '= 3
Dim result As IEnumerable(Of IEnumerable(Of Integer)) = Nothing

'Method 1:
result = From i In Enumerable.Range(0, count) Select collection.Skip(i * parts).Take(parts)

'Method 2:
result = Enumerable.Range(0, count).Select(Function(i) collection.Skip(i * parts).Take(parts))

For Each item In result
    Debug.WriteLine(String.Join(", ", item))
Next

1, 2, 3, 4
5, 6, 7, 8
9, 10

Mandatory extension method:

Public Module Extensions

    <System.Runtime.CompilerServices.Extension()>
    Public Function Split(Of TSource)(collection As IEnumerable(Of TSource), ByVal parts As Integer) As IEnumerable(Of IEnumerable(Of TSource))
        If (collection Is Nothing) Then Throw New ArgumentNullException("collection")
        If (parts < 1) Then Throw New ArgumentOutOfRangeException("parts")
        Dim count As Integer = collection.Count()
        If (count = 0) Then Return {}
        If (parts >= count) Then Return {collection}
        Return Enumerable.Range(0, CInt(Math.Ceiling(count / parts))).Select(Function(i) collection.Skip(i * parts).Take(parts))
    End Function

End Module

result = collection.Split(4)

这篇关于拆分集合为n个部分使用LINQ,在VB.Net的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆