Получить отдельные объекты списка из списка, используя LinQ

1

У меня есть список предметов.

class Item{
      public int Year { get; set; }
      public int QuarterIndex { get; set; }
}

Как конвертировать список в отдельный список?

Источник:

List<Item> items = new List<Item>(){
 new Item(){ Year = 2013, QuarterIndex = 1},
 new Item(){ Year = 2013, QuarterIndex = 2},
 new Item(){ Year = 2013, QuarterIndex = 3},
 new Item(){ Year = 2013, QuarterIndex = 1}
};

Результат:

target = new List<Item>(){
 new Item(){ Year = 2013, QuarterIndex = 1},
 new Item(){ Year = 2013, QuarterIndex = 2},
 new Item(){ Year = 2013, QuarterIndex = 3}
};
  • 1
    Вы должны: 1) Сделать Item реализующим IEquatable<Item> ; 2) использовать Distinct ()
Теги:
linq
list

1 ответ

8

Здесь простой, но потенциально менее эффективный способ, который работает без изменения самого класса:

items = items.GroupBy(i => new { i.Year, i.QuarterIndex })
    .Select(g => g.First())
    .ToList();

Другой способ - реализовать пользовательский IEqualityComparer<Item> который вы можете использовать для Distinct (и других методов в классе Enumerable):

public class ItemComparer : IEqualityComparer<Item>
{
    public bool Equals(Item lhs, Item rhs)
    {
        if(lhs == null || rhs == null) return false;
        return lhs.Year == rhs.Year && lhs.QuarterIndex == rhs.QuarterIndex;
    }

    public int GetHashCode(Item item)
    {
        if(item == null) return 0;
        unchecked
        {
            int hash = 23;
            hash = (hash * 31) + item.Year;
            hash = (hash * 31) + item.QuarterIndex;
            return hash;
        }
    }
}

Теперь это работает:

items = items.Distinct(new ItemComparer()).ToList();

Если вы можете/хотите изменить исходный класс, вы можете переопределить Equals + GetHashCode:

public class Item
{
    public int Year { get; set; }
    public int QuarterIndex { get; set; }

    public override bool Equals(object otherItem)
    {
        Item other = otherItem as Item;
        if (other == null) return false;
        return this.Equals(other);
    }

    public bool Equals(Item otherItem)
    {
        if(otherItem == null) return false;
        return Year == otherItem.Year && QuarterIndex == otherItem.QuarterIndex;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 23;
            hash = (hash * 31) + Year;
            hash = (hash * 31) + QuarterIndex;
            return hash;
        }
    }
}

Затем Distinct работает "автоматически":

items = items.Distinct().ToList();
  • 0
    Можете ли вы добавить это в Fiddler?
  • 0
    @ user1120418: вы имеете в виду .NET Fiddle ? Вот демонстрация ideone с использованием третьего способа: ideone.com/mahzQ0 Вы можете изменить его, чтобы использовать items = items.Distinct(new ItemComparer()).ToList(); продемонстрировать второй подход.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню