LINQ VB如何检查对象列表中的重复项

时间:2011-10-11 20:33:05

标签: vb.net linq group-by

我有一个对象列表,每个对象都有2个相关属性:“ID”和“Name”。让我们调用列表“lstOutcomes”。 如果至少有一个副本,我需要检查重复列表(意思是object1.ID = object2.ID等)并设置一个标志(valid = false或其他东西)。此外,当它失败时,向用户发送提及对象“名称”的消息会很好。

我确信我需要使用Group By运算符来执行此操作,但我不习惯在LINQ中执行此操作,并且那里的示例只是没有帮助我。 This article似乎接近我需要的东西,但并不完全,而且它在C#中。

这是一个开始刺...

Dim duplist = _
    (From o As objectType In lstOutcomes _
    Group o By o.ID Into g = Group _
    Let dups = g.Where(Function(h) g.Count > 1) _
    Order By dups Descending).ToArray

if duplist.count > 0 then
valid = false
end if

帮助?

5 个答案:

答案 0 :(得分:2)

我会用C#编写它,但希望你能把它转换成VB。它不使用join并且是O(n log n),我假设你有List<T>

lst.Sort();  //O(nlogn) part.

var duplicatedItems = lst.Skip(1).Where((x,index)=>x.ID == lst[index].ID);

答案 1 :(得分:1)

Dim itemsGroupedByID = lstOutcomes.GroupBy(Function(x) x.ID)
Dim duplicateItems = itemsGroupedByID.Where(Function(x) x.Count > 1) _
                                     .SelectMany(Function(x) x) _
                                     .ToList()

If duplicateItems.Count > 0
    valid = False
    Dim errorMessage = "The following items have a duplicate ID: " & _
                       String.Join(", ", duplicateItems.Select(Function(x) x.Name))
End If

答案 2 :(得分:1)

我将收回Saeed Amiri在C#中所说的内容并完成它。

        lst.Sort()
        Dim valid As Boolean = true
    dim duplicatedItems = lst.Skip(1) _
        .Where(Function(x,index) x.ID = lst(index).ID)

    Dim count As Integer = duplicatedItems.Count()
    For Each item As objectType In duplicatedItems
        valid = False
        Console.WriteLine("id: " & item.ID & "Name: " & item.Name)
    Next

答案 3 :(得分:1)

该项目落后,我只是像这样一起攻击它:

    ' For each outcome, if it is in the list of valid outcomes more than once, and it is not in the list of 
    ' duplicates, add it to the duplicates list.
    Dim lstDuplicates As New List(Of objectType)
    For Each outcome As objectType In lstOutcomes
        'declare a stable outcome variable
        Dim loutcome As objectType = outcome
        If lstOutcomes.Where(Function(o) o.ID = loutcome.ID).Count > 1 _
        AndAlso Not lstDuplicates.Where(Function(d) d.ID = loutcome.ID).Count > 0 Then
            lstDuplicates.Add(outcome)
        End If
    Next
    If lstDuplicates.Count > 0 Then
        valid = False
        sbErrors.Append("There cannot be multiple outcomes of any kind. The following " & lstDuplicates.Count & _
                        " outcomes are duplicates: ")
        For Each dup As objectType In lstDuplicates
            sbErrors.Append("""" & dup.Name & """" & " ")
        Next
        sbErrors.Append("." & vbNewLine)
    End If

答案 4 :(得分:0)

已经晚了,尽管可以帮助别人。

您可以使用一对非常干净的单线实现此目的:

Dim lstOutcomes As IList(Of T)

Dim FoundDuplicates As Boolean
FoundDuplicates = lstOutcomes.Any(Function(p) lstOutcomes.ToArray.Count(Function(q) p.ID = q.ID and p.Name=q.Name) > 1)

Dim ListOfDuplicates As IList(Of T)
ListOfDuplicates = lstOutcomes.Where(Function(p) lstOutcomes.ToArray.Count(Function(q) p.ID = q.ID And p.Name = q.Name) > 1)

然后,您可以清除重复项列表,使其仅包含一次重复项:

Dim CleanList as IList(of T)
For Each MyDuplicate As T in ListOfDuplicates
    If not CleanList.Any(function(p) p.ID = MyDuplicate.ID And p.Name = MyDuplicate.Name) then
        CleanList.Add(MyDuplicate)
    End If
Next

或者单线阅读,尽管阅读效果不佳

ListOfDuplicates.ForEach(sub(p) If not CleanList.Any(function(q) p.ID = q.ID And p.Name = q.Name) then CleanList.Add(p))

最后,作为对将来要求的预期,您应该将“重复项是什么”定义为单独的内容。委托对此非常方便:

Dim AreDuplicates as Func(of T, T, Boolean) = Function(a,b) a.ID = b.ID And a.Name = b.Name
FoundDuplicates = lstOutcomes.Any(Function(p) lstOutcomes.ToArray.Count(Function(q) AreDuplicates(p,q) ) > 1)