2011-12-14 3 views
3

Мне нужно выбрать отдельные дороги из коллекции дорог.Рекомендации LINQ по выбору отдельных элементов из коллекции

Я полагаю, что для этого я мог бы использовать 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# варианты принимаются, а;)

ответ

4

C#

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

(где DistinctBy является метод расширения определяется в Jon Skeet's отлично MoreLINQ проект)

+0

ок ... но я не закончил свой код, потому что мне нужно выбрать отличный (с различными .id) элементов – serhio

+0

Область ползучести!:-) ОК, обновлено .. –

+0

Я не уверен, могу ли я использовать MoreLINQ в коммерческом проприетарном проекте. – serhio

1

EDIT: я не получил первоначальное требование, изменил OrderBy на GroupBy/Select First. Вы также можете просто использовать Distinct, если переопределить метод Equals для сравнения Идентификаторы

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() 
+2

OfType умный, но вам не хватает Distinct. –

+0

Лучшее решение на мой взгляд, вы также можете удалить HighwayByIdComparer – Bas

+0

И OrderBy не вызван, это было (на полпути) решение, чтобы получить Distinct. –

0

Во-первых, вы могли бы взглянуть на этот блог: 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> правильно.

+0

'Dim myComparer As New HighwayByIdComparer' –

0

Вы можете использовать компаратор пользовательские равенства для 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(); 
1

'Дорожная модель

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 

' шоссе Comparer (используемый в отдельной статье)

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

Смежные вопросы