2013-03-09 1 views
3

У меня есть список объектов комнаты, каждый объект комнаты имеет атрибут здания;В C# Каков наилучший способ отфильтровать эту коллекцию?

public class Room 
{ 
     public string BuildingName; 
     public string Name 
} 

теперь я хочу, чтобы фильтровать свою коллекцию, где я только взять 1 номер из каждого здания (я не волнует, какой)

так, например

var room = new Room(){BuildingName ="Building 1", Name = "Room 1"}; 
var room2 = new Room(){BuildingName ="Building 1", Name = "Room 2"}; 
var room3 = new Room(){BuildingName ="Building 2", Name = "Room 3"}; 
var room4 = new Room(){BuildingName ="Building 2", Name = "Room 4"}; 
var room5 = new Room(){BuildingName ="Building 2", Name = "Room 5"}; 

var ListofRooms = new List<Room> {room, room2, room3, room4, room5}; 

в этом случае я хотел бы запустить этот список через функцию, которая возвращает массив с двумя элементами (по одному от каждого здания)

ответ

4

LINQ довольно удобен для такого рода задач:

var result = ListofRooms.GroupBy(room => room.BuildingName) 
         .Select(buildingGroup => buildingGroup.First()) 
         .ToList(); 

Что это такое, создайте ведро для каждого здания (состоящее из комнат в здании), затем выберите комнату из каждого ведра, прежде чем, наконец, материализовать выбранные комнаты в коллекцию.

Некоторые касательные точки:

  1. Стандарт C# соглашения об именовании диктуют, что локальные переменные должны быть названы в верблюжьего (listOfRooms), не PascalCase (ListofRooms).
  2. Если вы хотите, вы можете избавиться от скобок для конструкторы без параметров в объекте-инициализаторах, как это: new Room { BuildingName = "Building 1", Name = "Room 1" }

Если вы не хотите использовать LINQ для этого, я хотел бы сделать:

var seenBuildingNames = new HashSet<string>(); 
var result = new List<Room>(); 

foreach(var room in ListofRooms) 
{ 
    if(seenBuildingNames.Add(room.BuildingName)) 
    { 
     // First time we are encountering this building; add room to result. 
     result.Add(room); 
    } 
} 
0

Вы могли бы использовать этот подход:

var result = ListofRooms.Distinct(new BuildingEqualityComparer()); 

и класс BuildingEqualityComparer выглядит следующим образом:

public class BuildingEqualityComparer : IEqualityComparer<Room> 
{ 
    public bool Equals(Room x, Room y) 
    { 
     return x.BuildingName.Equals(y.BuildingName); 
    } 

    public int GetHashCode(Room obj) 
    { 
     return obj.BuildingName.GetHashCode(); 
    } 
} 

Этот подход фактически rarelly используется потому, что вам нужно сделать реализацию IEqualityComparer, которая является PITA, но это просто еще один способ достижения того, что вам нужно, так что если вам это нравится или найти его проще, использовать его !!!

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