已回答问题
谢谢Dan!你的代码完美无缺,今天你救了我的命!很多互联网给你好先生。原始
我受到社区的慷慨指导,使用LINQ最后一次在我的列表框中查找重复项。但是,我现在处于困境,因为我需要从多列列表视图中查找和删除重复项。我尝试使用LINQ,但它说listview对象不是“可查询的”。有没有办法让我只使用listview的一列来查找和删除重复项?
由于
更新
Private Shared Sub RemoveDuplicateListViewItems(ByVal listView As ListView)
Dim duplicates = listView.Items.Cast(Of ListViewItem)() _
.GroupBy(Function(item) item.Text)
.Where(Function(g) g.CountAtLeast(2))
.SelectMany(Function(g) g)
For Each duplicate As ListViewItem In duplicates
listView.Items.RemoveByKey(duplicate.Name)
Next
End Sub
这是我迄今为止感谢丹。仍然在“Dim duplicatelicates”行上出现错误。
更新2 以下是表单中模块和函数的代码:
Imports System.Runtime.CompilerServices
Module CountAtLeastExtension
<Extension()> _
Public Function CountAtLeast(Of T)(ByVal source As IEnumerable(Of T), ByVal minimumCount As Integer) As Boolean
Dim count = 0
For Each item In source
count += 1
If count >= minimumCount Then
Return True
End If
Next
Return False
End Function
End Module
Private Shared Sub RemoveDuplicateListViewItems(ByVal listView As ListView)
Dim duplicates = listView.Items.Cast(Of ListViewItem)() _
.GroupBy(Function(item) item.Text) _
.Where(Function(g) g.CountAtLeast(2)) _
.SelectMany(Function(g) g)
For Each duplicate As ListViewItem In duplicates
listView.Items.RemoveByKey(duplicate.Name)
Next
End Sub
我打电话给代码现在运行正常。但它并没有删除重复项:
也许通过这个截图你可以看到我在这里要做什么。非常感谢你对我这么耐心!
答案 0 :(得分:1)
好吧,你需要一些方法来确定两个ListViewItem
对象是否重复。
一旦到位,实施就相当简单。
假设您想要考虑两个项目,如果第一列中的文本相同(例如)。然后,您可以编写一个快速IEqualityComparer<ListViewItem>
实现,例如:
class ListViewItemComparer : IEqualityComparer<ListViewItem>
{
public bool Equals(ListViewItem x, ListViewItem y)
{
return x.Text == y.Text;
}
public int GetHashCode(ListViewItem obj)
{
return obj.Text.GetHashCode();
}
}
然后您可以删除重复项:
static void RemoveDuplicateListViewItems(ListView listView)
{
var uniqueItems = new HashSet<ListViewItem>(new ListViewItemComparer());
for (int i = listView.Count - 1; i >= 0; --i)
{
// An item will only be added to the HashSet<ListViewItem> if an equivalent
// item is not already contained within. So a return value of false indicates
// a duplicate.
if (!uniqueItems.Add(listView.Items[i]))
{
listView.Items.RemoveAt(i);
}
}
}
更新:上述代码会多次删除ListView
中出现的任何项目的重复;也就是说,它会留下每个实例。如果您想要的行为实际上是删除多次出现的任何项目的所有实例,则该方法会略有不同。
这是你可以做到的一种方式。首先,定义以下扩展方法:
public static bool CountAtLeast<T>(this IEnumerable<T> source, int minimumCount)
{
int count = 0;
foreach (T item in source)
{
if ((++count) >= minimumCount)
{
return true;
}
}
return false;
}
然后,找到像这样的重复:
static void RemoveDuplicateListViewItems(ListView listView)
{
var duplicates = listView.Items.Cast<ListViewItem>()
.GroupBy(item => item.Text)
.Where(g => g.CountAtLeast(2))
.SelectMany(g => g);
foreach (ListViewItem duplicate in duplicates)
{
listView.Items.RemoveByKey(duplicate.Name);
}
}
更新2 :听起来您已经能够将上述大部分内容转换为VB.NET了。给您带来麻烦的那一行可以写成如下:
' Make sure you have Option Infer On. '
Dim duplicates = listView.Items.Cast(Of ListViewItem)() _
.GroupBy(Function(item) item.Text) _
.Where(Function(g) g.CountAtLeast(2)) _
.SelectMany(Function(g) g)
另外,如果以上述方式使用CountAtLeast
方法时遇到任何问题,则需要使用ExtensionAttribute
类在VB.NET中编写扩展方法:
Module CountAtLeastExtension
<Extension()> _
Public Function CountAtLeast(Of T)(ByVal source As IEnumerable(Of T), ByVal minimumCount As Integer) As Boolean
Dim count = 0
For Each item in source
count += 1
If count >= minimumCount Then
Return True
End If
Next
Return False
End Function
End Module