简体   繁体   中英

Selecting Unique Elements From a List in C#

如何从列表{0, 1, 2, 2, 2, 3, 4, 4, 5}中选择唯一元素,以便我得到{0, 1, 3, 5} ,有效地删除重复的所有实例元素{2, 4}

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 }
var nums = new int{ 0...4,4,5};
var distinct = nums.Distinct();

make sure you're using Linq and .NET framework 3.5.

With lambda..

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);

C# 2.0 solution:

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;
    }
}

Here is another way that works if you have complex type objects in your List and want to get the unique values of a property:

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

Or to get distinct values:

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

If your property is also a complex type you can create a custom comparer for the Distinct(), such as Distinct(OrderComparer), where OrderComparer could look like:

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();
    }
}

If Linq isn't available to you because you have to support legacy code that can't be upgraded, then declare a Dictionary, where the first int is the number and the second int is the number of occurences. Loop through your List, loading up your Dictionary. When you're done, loop through your Dictionary selecting only those elements where the number of occurences is 1.

I believe Matt meant to say:

 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;
 }

There are many ways to skin a cat, but HashSet seems made for the task here.

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 );
}

The output:

0 1 2 3 4 5

Here's a solution with no LINQ:

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

// This assumes the numbers are sorted
var noRepeats = new List<int>();
int temp = numbers[0]; // Or .First() if using IEnumerable
var count = 1;
for(int i = 1; i < numbers.Length; i++) // Or foreach (var n in numbers.Skip(1)) if using IEnumerable
{
    if (numbers[i] == temp) count++;
    else
    {
        if(count == 1) noRepeats.Add(temp);
        temp = numbers[i];
        count = 1;
    }
}
if(count == 1) noRepeats.Add(temp);

Console.WriteLine($"[{string.Join(separator: ",", values: numbers)}] -> [{string.Join(separator: ",", values: noRepeats)}]");

This prints:

[0,1,2,2,2,3,4,4,5] -> [0,1,3,5]

In .Net 2.0 I`m pretty sure about this solution:

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM