views:

1503

answers:

7

I have a list of integers in C#. I wish to remove duplicates. In C++ I would run it through the std::sort and then std::unique algorithms for a very efficient way of obtaining the unique list.

What's the best way to do the same thing in C#? In other words, I'm looking for a more elegant way to do the following code:

    private static int[] unique(int[] ids)
    {
        IDictionary<int, object> d = new Dictionary<int, object>();
        foreach(int i in ids)
            d[i] = null;

        int[] results = new int[d.Count];
        int j = 0;
        foreach(int id in d.Keys)
            results[j++] = id;

        return results;
    }
+7  A: 

What version of .NET are you using?

In .NET 3.5 that's as simple as calling the Distinct() extension method and then ToArray() if you really need an array again.

For example:

int[] x = new[] { 1, 4, 23, 4, 1 };
int[] distinct = x.Distinct().ToArray();
// distinct is now { 1, 4, 23 } (but not necessarily in that order)
Jon Skeet
A: 

Alas I only have .NET 2.0 to work with

Paul Hollingsworth
+1  A: 

Even with .NET 2.0, you could get the same with LINQBridge. This will be easier to use with C# 3.0 (even with .NET 2.0), but should be usable with C# 2.0 and .NET 2.0 - you'd simply have to use Enumerable.Distinct(x) rather than x.Distinct();

Of course, ultimately these are just pre-wrapped versions of the code you posted earlier (give-or-take things like iterator blocks), so you could just push that code into a utility class and (re)use it from there.

Marc Gravell
+3  A: 

if you considering STL methods as "very efficient", so use following:

       var vals = new List<int> { 1, 2, 3, 2, 1, 2, 3, 2, 3, 4, 3, 2, 3 };
       vals.Sort();
       var uniques = new HashSet<int>(vals);

For 2.0 equivalent

List<int> vals = new List<int>();
vals.Add(1);
vals.Add(2);
vals.Add(3);
vals.Add(2);
...
vals.Sort();
List<int> uniques = new List<int>();
vals.ForEach(delegate(int v) {
 if (!uniques.Contains(v)) uniques.Add(v);
});
Tamir
I don't think there's much benefit from the Sort - as I understand it, a HashSet is in no particular order. Plus it is .NET 3.5 (the OP only has .NET 2.0)
Marc Gravell
A: 

On a half-way related note, C# has a System.Array.Sort static method that you can use to sort real arrays without using a collection.

R. Bemrose
A: 

I don't know how big your collection is, but if you aren't dealing with thousands of integers this might be good enough:

public IEnumerable<int> unique(int[] ids)
{
    List<int> l = new List<int>();
    foreach (int id in ids)
    {
        if (!l.Contains(id))
        {
            l.Add(id);
            yield return id;
        }
    }
}
slf
A: 
  private static List<T> GetUnique<T>(List<T> list) where T : IEquatable<T>
  {
     list.Sort();
     int count = list.Count;
     List<T> unique = new List<T>(count);
     T last = default(T);
     for (int i = 0; i < count; i++)
     {
        T val = list[i];
        if (i != 0 && last.Equals(val)) continue;
        last = val;
        unique.Add(val);
     }
     return unique;
  }
Cine