簡體   English   中英

LINQ建議從集合中選擇不同的元素

[英]LINQ advice on selecting distinct elements from a collection

我需要從道路收集中選擇不同的高速公路。

我想我可以使用LINQ。

我有(存根代碼)

  Dim roads As List(Of Roads) = myRegion.Roads
  Dim highways As New List(Of Highway)

  For Each road In roads
    If road.RoadType = RoadType.Highway Then
      highways.Add(DirectCast(road, Highway))
    End If
  Next ic

  ' Now I think sorting them by .Id and then remove duplicates '
  Dim myComparer As New HighwayByIdComparer
  highways.Sort(myComparer)

也接受C#變體;)

C#:

return myRegion.Roads
    .Where(x => x.RoadType == RoadType.Highway)
    .DistinctBy(x => x.Id);

(其中DistinctBy是Jon Skeet優秀的MoreLINQ項目中定義的擴展方法)

編輯:我沒有得到原始要求,將OrderBy更改為GroupBy / Select First。 如果重寫Equals方法來比較ID,也可以簡單地使用Distinct

var highways = roads.OfType<Highway>()
          .GroupBy(x => x.Id)
          .Select(x => x.First())
          .ToList()

或者在VB.Net中:

Dim highways = roads.OfType(Of Highway)().
       GroupBy(Function(road) road.Id).
       Select(Function(x) x.First()).
       ToList()

'道路模型

Public Class Road
Public Property Id As Integer
Public Property Name As String
Public Property RoadType As RoadType
End Class 

'公路模型

Public Class Highway
Public Property Id As Integer
Public Property Name As String 
End Class

'RoadType Enum

Public Enum RoadType

Residential
Highway
OffRoad
End Enum

'公路比較器(用於distinct子句)

Public Class HigwayNameComparer
Implements IEqualityComparer(Of Highway)
Public Function Equals(ByVal x As Highway, ByVal y As Highway) As Boolean Implements IEqualityComparer(Of Highway).Equals
    Return x.Name = y.Name
End Function

Public Function GetHashCode(ByVal obj As Highway) As Integer Implements IEqualityComparer(Of Highway).GetHashCode
    Return obj.Name.GetHashCode()
End Function
End Class

'控制台應用

Sub Main()
    Dim roads As New List(Of Road)
    roads.Add(New Road() With {.Id = 1, .Name = "Barclays Road", .RoadType = RoadType.Residential})
    roads.Add(New Road() With {.Id = 2, .Name = "Effie Road", .RoadType = RoadType.Residential})
    roads.Add(New Road() With {.Id = 3, .Name = "Out Road", .RoadType = RoadType.OffRoad})
    roads.Add(New Road() With {.Id = 4, .Name = "M4", .RoadType = RoadType.Highway})
    roads.Add(New Road() With {.Id = 5, .Name = "M4", .RoadType = RoadType.Highway})


    Dim results = (From road In roads Where road.RoadType = RoadType.Highway
            Select New Highway With {.Id = road.Id, .Name = road.Name}).Distinct(New HigwayNameComparer())


    For Each highway As Highway In results
        Console.WriteLine("{0}", highway.Name)
    Next

    Console.ReadLine()


End Sub 

---輸出:M4

首先,你可以看看這篇博客文章: http//blogs.msdn.com/b/csharpfaq/archive/2009/03/25/how-to-use-linq-methods-to-compare-objects- of-custom-types.aspx 這表明您需要創建EqualityComparer<T>而不是簡單地將其傳遞給Distinct運算符。

roads.Where(r => r.RoadType == RoadType.Highway).Distinct(myComparer);

假設myComparer實際上正確地實現了EqualityComaprer<T>

您可以使用Road的自定義相等比較器來使用Distinct()

public class RoadComparer : IEqualityComparer<Road>
{
    public bool Equals(Road x, Road y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Road obj)
    {
        return obj.Id.GetHashCode();
    }
}

var results = myRegion.Roads
                      .OfType<Highway>()
                      .Distinct(new RoadComparer())
                      .OrderBy( road => road.Id)
                      .ToList();   

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM