0

This is my object:

public class MyObject
{
    public int id { get; set; }
    public string fileName { get; set; }
    public string browser { get; set; }    
    public string protocol { get; set; }    
    public string family { get; set; }
}

and i have a list of my object:

List<Capture> list = db.Captures.Where(x => x.family == "Web").ToList();

What i want to do is get new list that removed the duplicate protocol. for example if i have in my list 10 object and 9 of them with protocol DOC and 1 PDF i want a new list with only 2 object DOC and 1 PDF

user979033
  • 5,430
  • 7
  • 32
  • 50

4 Answers4

1

There are several ways to do this, depending on how you generally want to use the instances of your MyObject class.

The easiest one is implementing the IEquatable<T> interface so as to compare only the protocol fields:

public class MyObject : IEquatable<MyObject>
{
    public sealed override bool Equals(object other)
    {
        return Equals(other as MyObject);
    }

    public bool Equals(MyObject other)
    {
        if (other == null) {
            return false;
        } else {
            return this.protocol == other.protocol;
        }
    }

    public override int GetHashCode()
    {
        return protocol.GetHashCode();
    }
}

You can then call Distinct before converting your enumerable into a list.


Alternatively, you can use the Distinct overload that takes an IEqualityComparer.

The equality comparer would have to be an object that determines equality based on your criteria, in the case described in the question, by looking at the protocol field:

public class MyObjectEqualityComparer : IEqualityComparer<MyObject>
{
    public bool Equals(MyObject x, MyObject y)
    {
        if (x == null) {
            return y == null;
        } else {
            if (y == null) {
                return false;
            } else {
                return x.protocol == y.protocol;
            }
        }
    }

    public int GetHashCode(MyObject obj)
    {
        if (obj == null) {
            throw new ArgumentNullException("obj");
        }

        return obj.protocol.GetHashCode();
    }
}
O. R. Mapper
  • 20,083
  • 9
  • 69
  • 114
1

I believe this is the simplest approach: The following will group list by protocol and then get the first instance from each group to produce an enumerable with one instance of each type of protocol.

list.GroupBy(x => protocol, x => x)
    .SelectMany(k, v => v.First());
Daniel Gimenez
  • 18,530
  • 3
  • 50
  • 70
0

Select distinct protocols, loop on them and subselect only first object of the same protocol - thus you'll get the list you need.

LINQ2Vodka
  • 2,996
  • 2
  • 27
  • 47
  • Why the restriction to `count > 1`? The question says nothing about that. – O. R. Mapper Nov 10 '13 at 15:39
  • @O.R.Mapper " get new list that removed the duplicate protocol" – LINQ2Vodka Nov 10 '13 at 15:40
  • `GroupBy` already produces groups by protocol; the OP can just use the first item of each group (or somehow compile one item per group in whichever way he/she likes). Putting the grouped items back together into one unidimensional list and removing anything from there with `RemoveRange` seems somewhat nonsensical to me. – O. R. Mapper Nov 10 '13 at 15:43
  • @O.R.Mapper deleting the first option, getting ahead of myself in rating race :) – LINQ2Vodka Nov 10 '13 at 16:07
  • Actually, I didn't think the first option with `GroupBy` was that bad, *if* you use it to do something with all of the grouped items. Such as, creating a "mixed item" that represents all items of the given protocol, somehow. (I'm not sure the OP has considered whether just taking *any* one item of each protocol will do.) – O. R. Mapper Nov 10 '13 at 16:11
0

You could either use Distinct, or use the same solution provided here:

Distinct() with lambda?

Community
  • 1
  • 1
Jordy Langen
  • 3,591
  • 4
  • 23
  • 32