7

I am wondering how can I achieve this?

I want to get only distinct names from a collection of objects

MyObject a = new Object();
a.Name = 'One';
a.Value = '10';


MyObject b = new Object();
b.Name = 'One';
b.Value = '15';


MyObject c = new Object();
c.Name = 'Two';
c.Value = '10';

So I want to get only back the name. I don't care about the value in this case just the name.

So I tried

//add all the objects to a collection.

myCollection.Disinct()..Select(x => new MyClassToStore() {Text = x.Name, Value = x.Name}).ToList());

However I need to do distinct at the property level not at the object level. So I want back "One" and "Two". Right now I get "One", "One" and "Two" back.

I see a library called morelinq but I not sure if I should use it as it still in beta and does not seem to be developed on anymore.

Plus a whole library for one extract query I am not sure if it is worth it.

user541686
  • 205,094
  • 128
  • 528
  • 886
chobo2
  • 83,322
  • 195
  • 530
  • 832

5 Answers5

23

Maybe something like this can help?

var distinctItems = items
     .GroupBy(x => x.PropertyToCompare)
     .Select(x => x.First());
Marino Šimić
  • 7,318
  • 1
  • 31
  • 61
  • how could I get stick it into MyClassToStore – chobo2 Apr 09 '11 at 21:52
  • var distinctitems = myCollection.GroupBy(x => x.Name).Select(x => x.First()).Select(new MyClassToStore() {Text = x.Name, Value = x.Name}) i suppose, altough i did not get exactly what you need. because using the same property (name) twice is a bit awkward... I think that you should listen to Cameron if you need just names... – Marino Šimić Apr 09 '11 at 22:02
15

This populates both the Text and Value fields:

   myCollection.Select(x => x.Name).Distinct()
      .Select(x => new MyClassToStore { Text = x, Value = x }).ToList();
PHeiberg
  • 29,411
  • 6
  • 59
  • 81
6

If you just want back distinct names, you can use:

myCollection.Select(x => x.Name).Distinct().ToList();
Cameron
  • 96,106
  • 25
  • 196
  • 225
3

You can implement your class so the linq distinct operator does not use the default equality comparer.

class YourClass:IEquatable<YourClass> 
{

... Your implementation details. ...

    public bool Equals(YourClass other)
    {
        if (Object.Equals(this, other))
        {
            return true;
        }
        else
        {
            if(Name == other.Name && Value == other.Value)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

 public override int GetHashCode()
 {
     return Name.GetHashCode() ^ Value.GetHashCode();
 }

}
Alessandro Incarnati
  • 7,018
  • 3
  • 38
  • 54
Dave M
  • 31
  • 1
2

Personally I suggest you override operator == and != and determine how and why an object is unique there. Then use the Distinct() call on the collection.

You do have to be careful with null values, see Microsoft's Guidelines for Overloading Equals() and Operator == (C# Programming Guide).

Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
  • 1
    To be clear, do not override the `==` or `!=` operator in any sort of global context. What's suggested here is to override the `Equals` and `==` operator your class inherits from `object` – Andy_Vulhop Jan 29 '14 at 17:17