Tim*_*ter 4 .net linq vb.net linq-to-objects linq-to-dataset
LINQ让我疯狂.为什么以下查询不返回重复项,而它只使用一个标识符?我的错误在哪里?
' generate some test-data '
Dim source As New DataTable
source.Columns.Add(New DataColumn("RowNumber", GetType(Int32)))
source.Columns.Add(New DataColumn("Value1", GetType(Int32)))
source.Columns.Add(New DataColumn("Value2", GetType(Int32)))
source.Columns.Add(New DataColumn("Text", GetType(String)))
Dim rnd As New Random()
For i As Int32 = 1 To 100
Dim newRow = source.NewRow
Dim value = rnd.Next(1, 20)
newRow("RowNumber") = i
newRow("Value1") = value
newRow("Value2") = (value + 1)
newRow("Text") = String.Format("RowNumber{0}-Text", i)
source.Rows.Add(newRow)
Next
' following query does not work, it always has Count=0 '
' although it works with only one identifier '
Dim dupIdentifiers = From row In source
Group row By grp = New With {.Val1 = row("Value1"), .Val2 = row("Value2")}
Into Group
Where Group.Count > 1
Select idGroup = New With {grp.Val1, grp.Val2, Group.Count}
Run Code Online (Sandbox Code Playgroud)
编辑:以下是完整的解决方案,感谢@Jon Skeet的回答 :)
Dim dupKeys = From row In source
Group row By grp = New With {Key .Val1 = CInt(row("Value1")), Key .Val2 = CInt(row("Value2"))}
Into Group Where Group.Count > 1
Select RowNumber = CInt(Group.FirstOrDefault.Item("RowNumber"))
Dim dupRows = From row In source
Join dupKey In dupKeys
On row("RowNumber") Equals dupKey
Select row
If dupRows.Any Then
' create a new DataTable from the first duplicate rows '
Dim dest = dupRows.CopyToDataTable
End If
Run Code Online (Sandbox Code Playgroud)
分组的主要问题是我必须使它们成为key属性.上面代码中的下一个问题是从原始表中获取重复的行.因为几乎每一行都有一个副本(根据两个字段),结果DataTable包含99个100行,而不仅仅是19个重复值.我只需要选择第一个重复行并将它们与PK上的原始表连接起来.
Select RowNumber = CInt(Group.FirstOrDefault.Item("RowNumber"))
Run Code Online (Sandbox Code Playgroud)
虽然这适用于我的情况,也许有人可以解释我如何只选择原始表中的重复项,如果我只有复合键.
编辑:我自己回答了问题的最后一部分,所以这就是我需要的:
Dim dups = From row In source
Group By grp = New With {Key .Value1 = CInt(row("Value1")), Key .Value2 = CInt(row("Value2"))}
Into Group Where Group.Count > 1
Let Text = Group.First.Item("Text")
Select Group.First
If dups.Any Then
Dim dest = dups.CopyToDataTable
End If
Run Code Online (Sandbox Code Playgroud)
我需要Let-Keyword以便将其他列保持在相同的上下文中并仅返回分组的dup的第一行.通过这种方式,我可以用来CopyToDataTable从重复的行创建一个DataTable.
总共只有几行代码(我可以保存第二个查询以查找原始表中的行)以在多个列上查找重复项并创建它们的DataTable.
问题是匿名类型在VB中的工作方式- 默认情况下它们是可变的; 仅Key包含用于散列和相等的属性.试试这个:
Group row By grp = New With {Key .Val1 = row("Value1"), Key .Val2 = row("Value2")}
Run Code Online (Sandbox Code Playgroud)
(在C#中,这不是问题 - C#中的匿名类型在所有属性中始终是不可变的.)
| 归档时间: |
|
| 查看次数: |
2813 次 |
| 最近记录: |