在VB.Net中,如果我有这样的集合:
Dim collection As IEnumerable(Of Integer) = Enumerable.Range(0, 99)
我如何将它分成不确定数量的元素的组/ Ienumerables?
使用 LINQ 查询(不是 MORELinq 或任何其他第三方库)
不写Function
,只是使用(或附加到集合) LINQ 查询,避免插入自定义和通用过程来分割部分。
未生成Anonymous
类型(因为我会尊重VB.Net Option
语句)。
我已经阅读过这些问题,但我无法将C# LINQ 查询正确地翻译成VB.Net(甚至在线翻译失败并需要进行大量修改):
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
这是我尝试从那些S.O.中给出的解决方案中适应的两种不同方法。上面的问题,但我的翻译不起作用,第一个无法编译,因为分组依据的条件和第二个不生成分割集合,它每个生成一个集合元素:
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))()
所以,如果我有这样的源集合:
Dim collection As IEnumerable(Of Integer) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
假设我有那个想象的LINQ查询,它可以通过变量splits
上指定的值拆分成名为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)
如果我选择parts
值 4 ,那么结果将是Enumerable(Of IEnumerable(Of Integer))
,其中包含 3 个集合,其中:< / p>
splits(0) = {1, 2, 3, 4}
splits(1) = {5, 6, 7, 8}
splits(2) = {9, 10}
如果我选择parts
值 5 ,那么结果将是Enumerable(Of IEnumerable(Of Integer))
,其中包含 2 个集合,其中:< / p>
splits(0) = {1, 2, 3, 4, 5}
splits(1) = {6, 7, 8, 9, 10}
如果我选择parts
值为 1 ,则结果将为I Enumerable(Of IEnumerable(Of Integer))
,其中包含相同的源集合,因为我选择拆分为 1 部分:
splits(0) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
如果我选择parts
值 10 ,那么结果将是Enumerable(Of IEnumerable(Of Integer))
,其中包含 10 个集合,每个集合一个源示例集合的每个值:
splits(0) = {1}
splits(1) = {2}
splits(2) = {3}
and so on...
答案 0 :(得分:4)
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
强制性扩展方法:
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)
答案 1 :(得分:2)
您正在寻找的查询可能如下所示:
Dim partitionSize As Integer = 4
Dim collection As IEnumerable(Of Integer) = Enumerable.Range(0, 100)
Dim parts As Integer = collection.Count \ partitionSize
Dim splits = (From i In collection
Group i By key = i Mod parts Into g = Group
Select key, g)
这取决于您展示的样本。但是,如果实际数据的排列更随机,这种方式将使用根据索引值分组的索引值:
Dim partitionSize As Integer = 4
Dim collection As IEnumerable(Of Integer) = Enumerable.Range(100, 100)
Dim parts As Integer = collection.Count \ partitionSize
Dim splits = (From i In Enumerable.Range(0, 100)
Group collection(i) By key = i Mod parts Into g = Group
Select key, g)
您的帖子说您不想使用匿名类型。但是,Group By使用匿名类型。您可以通过将集合强制转换为Dictionary来使匿名类型成为临时类型:
Dim splits = (From i In Enumerable.Range(0, 100)
Group collection(i) By key = i Mod parts Into g = Group
Select key, g).ToDictionary(Function(x) x.key, Function(x) x.g)
答案 2 :(得分:2)
发布的答案很晚但只是想在我看来显示我的版本简单:)以下是查询: -
Dim result4 As IEnumerable(Of IEnumerable(Of Integer)) = collection
.Select(Function(v, i) New With {.Value = v, .Index = i}) _
.GroupBy(Function(x) x.Index \ 4) _
.Select(Function(x) x.Select(Function(z) z.Value))
这是表示: -
1.我使用了Select
的{{3}}重载来获取索引及其值
2.一旦我们得到索引,步骤2就是简单的数学,因为我们将索引(0,1,2 ---)除以我们想要的部分数量(在这种情况下为4)并简单地将它们组合在一起。
3.由于在步骤1中我们分别预测了value
和index
,因此在最后一步中只需选择值。
以下是this,其中包含2个示例。