将列表分成多个部分 - VB转换失败

5

尝试编写一个方法,将列表拆分为子列表。

Private Function SplitIdsIntoChunks(ByVal keys As List(Of String)) As List(Of List(Of String))
    Return keys _
        .Select(Function(x, i) New With {Key .Index = i, Key .Value = x}) _
        .GroupBy(Function(x) (x.Index / 10000)) _
        .Select(Function(x) x.Select(Function(v) v.Value).ToList()) _
        .ToList()
End Function

我使用了来自这里的C#解决方案。

C#解决方案运行良好。

我用VB编写的版本返回一个只有一个元素的列表集合,而不是10000个。 我哪里错了?

提前感谢。

编辑1:

用法:

Dim chunks As List(Of List(Of String)) = SplitIdsIntoChunks(keys)

'Keys'内容:

输入图像描述

我的方法返回一个列表,其中每个列表中只有一个项目:

输入图像描述

期望结果:两个列表的列表 - 第一个列表有10000个项目,第二个列表有6256个项目。


即使在这种情况下可能没有必要回答你的问题,你能否发布一下你在VB.NET中所做的事情?我主要是这么说,因为你已经提到了一个具体的错误,所以将其添加进来可能会稍微装饰一下这个问题。 - Panzercrisis
3个回答

9
主要问题在于,使用 c# 对一个 int 类型的数进行除法运算 x.Index / 3 会得到一个整数结果。而在 VB 中,标准的除法运算符 / 总是返回一个 Double,因此每个项目都有一个唯一的分组。例如:{.33, .333333, .333334} 等。
“诀窍”在于使用整数除法运算符 \ 来获得整数结果。我还添加了一个 chunksize 参数,使其更加灵活和可重用:
Private Function SplitIntoChunks(keys As List(Of String), chunkSize As Integer) As List(Of List(Of String))
    Return keys.
            Select(Function(x, i) New With {Key .Index = i, Key .Value = x}).
            GroupBy(Function(x) (x.Index \ chunkSize)).
            Select(Function(x) x.Select(Function(v) v.Value).ToList()).
            ToList()
End Function

另一个区别是c#在行延续方面非常灵活,因此点号可以出现在行的开头或结尾。VB(自VS2010以来)支持隐式行延续,在许多内容(包括成员限定符字符(点号.))之后,因此您可以摆脱显式的行延续符(" _")。

用法:

' split list of 1000 into 300 chunks
Dim splits = SplitIntoChunks(myList, 300)

For n As Integer = 0 To splits.Count - 1
    Console.WriteLine("Split {0} has {1} items", n.ToString(), splits(n).Count)
Next

输出/结果:

分割0有300个项目
分割1有300个项目
分割2有300个项目
分割3有100个项目

请注意,链接的C#帖子上有关于各种方法性能的大量评论。这只是让它工作,一些替代方法可能会根据实际分割的内容表现更好。这里使用的SkipTake方法也很有趣。


2

那段代码的正确翻译是:

Private Function SplitIdsIntoChunks(ByVal keys As List(Of String)) As List(Of List(Of String))
    Return keys _
        .Select(Function(x, i) New With {Key .Index = i, Key .Value = x}) _
        .GroupBy(Function(x) (x.Index \ 10000)) _
        .Select(Function(x) x.Select(Function(v) v.Value).ToList()) _
        .ToList()
End Function

请注意/\之间的区别,前者返回浮点数,后者返回整数。

-1
在链接的答案中,第一个选择器是这样的。
.Select((x, i) => new { Index = i, Value = x })

你的代码中有

.Select(Function(x, i) New With {Key .Index = i, Key .Value = x})

为什么重复键名?我认为你只需要指定匿名类型的属性即可。

从这个问题来看,也许C#中的每个属性都是Key?在这个领域,VB和C#之间似乎存在一些差异。 - Jeff B
C#代码创建了一个具有两个属性Index和Value的匿名类型,为什么VB代码需要Key?不起作用吗?请发布您使用的代码和错误消息。在VB代码中不应该需要任何Key。 - CheGueVerra
New With {Key .Index = i, Key .Value = x} 创建了一个具有两个属性 IndexValue 的匿名类型。在使用匿名类型时,始终使用 Key 关键字是一个好习惯,因为它使得更容易理解该类型的行为。 - sloth
我在VB代码中从未使用过那个东西...我一直使用 new With { .PropA = x, .PropB = y },这就像在 C# 中的 new { PropA = x, PropB = y }。我不明白为什么需要在其中加上关键字 Key。有人能解释一下或者帮我找到相关内容吗? - CheGueVerra
例如,看一下这个问题:相同的 (?) C# 和 VB.NET LINQ 查询返回不同的结果 - sloth
非常感谢,我之前完全不知道,你的帮助真的很有用! - CheGueVerra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接