Выбор уникальных элементов из списка в C # - PullRequest
18 голосов
/ 15 ноября 2008

Как выбрать уникальные элементы из списка {0, 1, 2, 2, 2, 3, 4, 4, 5}, чтобы я получил {0, 1, 3, 5}, эффективно удаляя все экземпляры повторяющихся элементов {2, 4}?

Ответы [ 9 ]

31 голосов
/ 15 ноября 2008
var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };

var uniqueNumbers =
    from n in numbers
    group n by n into nGroup
    where nGroup.Count() == 1
    select nGroup.Key;

// { 0, 1, 3, 5 }
16 голосов
/ 15 ноября 2008
var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();

убедитесь, что вы используете Linq и .NET Framework 3.5.

12 голосов
/ 16 января 2009

с лямбда ..

var all = new[] {0,1,1,2,3,4,4,4,5,6,7,8,8}.ToList();
var unique = all.GroupBy(i => i).Where(i => i.Count() == 1).Select(i=>i.Key);
10 голосов
/ 15 ноября 2008

C # 2.0 решение:

static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
{
    Dictionary<T, int> counts = new Dictionary<T, int>();

    foreach (T item in things)
    {
        int count;
        if (counts.TryGetValue(item, out count))
            counts[item] = ++count;
        else
            counts.Add(item, 1);
    }

    foreach (KeyValuePair<T, int> kvp in counts)
    {
        if (kvp.Value == 1)
            yield return kvp.Key;
    }
}
8 голосов
/ 17 февраля 2012

Вот еще один способ, который работает, если у вас есть объекты сложного типа в вашем Списке и вы хотите получить уникальные значения свойства:

var uniqueValues= myItems.Select(k => k.MyProperty)
                  .GroupBy(g => g)
                  .Where(c => c.Count() == 1)
                  .Select(k => k.Key)
                  .ToList();

Или получить разные значения:

var distinctValues = myItems.Select(p => p.MyProperty)
                            .Distinct()
                            .ToList();

Если ваше свойство также является сложным типом, вы можете создать пользовательский компаратор для Distinct (), например Distinct (OrderComparer), где OrderComparer может выглядеть так:

public class OrderComparer : IEqualityComparer<Order>
{
    public bool Equals(Order o1, Order o2)
    {
        return o1.OrderID == o2.OrderID;
    }

    public int GetHashCode(Order obj)
    {
        return obj.OrderID.GetHashCode();
    }
}
3 голосов
/ 15 ноября 2008

Полагаю, Мэтт хотел сказать:

 static IEnumerable<T> GetUniques<T>(IEnumerable<T> things)
 {
     Dictionary<T, bool> uniques = new Dictionary<T, bool>();
     foreach (T item in things)
     {
         if (!(uniques.ContainsKey(item)))
         {
             uniques.Add(item, true);
         }
     }
     return uniques.Keys;
 }
3 голосов
/ 15 ноября 2008

Если Linq недоступен для вас, потому что вы должны поддерживать устаревший код, который не может быть обновлен, объявите словарь, в котором первое int - это число, а второе int - это число случаев. Перебирайте ваш список, загружая ваш словарь. Когда вы закончите, переберите свой словарь, выбирая только те элементы, где число вхождений равно 1.

2 голосов
/ 20 февраля 2012

Есть много способов снять шкуру с кошки, но, похоже, HashSet для этой задачи здесь.

var numbers = new[] { 0, 1, 2, 2, 2, 3, 4, 4, 5 };

HashSet<int> r = new HashSet<int>(numbers);

foreach( int i in r ) {
    Console.Write( "{0} ", i );
}

Выход:

0 1 2 3 4 5

0 голосов
/ 11 декабря 2010

В .Net 2.0 я почти уверен в этом решении:

public IEnumerable<T> Distinct<T>(IEnumerable<T> source)
{
     List<T> uniques = new List<T>();
     foreach (T item in source)
     {
         if (!uniques.Contains(item)) uniques.Add(item);
     }
     return uniques;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...