-2

I have a class Items with properties (Id, Name, DrugCode1, DrugCode2).

The List of Items is populated with duplicated items.

For eg.:

------------------------------------------
Id        Name     DrugCode1  DrugCode2
------------------------------------------
1         Item1       2         3
2         Item2       3         2
3         Item3       4         3
1         Item1       3         2
3         Item3       3         4

If the DurgCode1 and DrugCode2 are reversed then we consider the items to be duplicates

eg:

1         Item1       2         3
1         Item1       3         2

The above 2 itmes are considered duplicate since the DrugCode1 and DrugCode2 are reversed. We just need to fetch only one item.

How to remove the duplicates in the list using linq?

No Idea For Name
  • 11,411
  • 10
  • 42
  • 70
BlindBandit
  • 54
  • 1
  • 6
  • possible duplicate of [How to use LINQ Distinct() with multiple fields](http://stackoverflow.com/questions/10719928/how-to-use-linq-distinct-with-multiple-fields) – Ram Singh Aug 26 '13 at 11:42
  • 1
    What about `Item3`? It also appears two times, with codes `4,3` and `3,4`... – MBender Aug 26 '13 at 11:47

4 Answers4

3

Since you have not tagged the linq-provider i presume Linq-To-Objects. You could use an anonymous type in the same order for GroupBy:

IEnumerable<Item> distinctItems = items
  .GroupBy(i => new { Min=Math.Min(i.DrugCode1, i.DrugCode2),Max=Math.Max(i.DrugCode1, i.DrugCode2) })
  .Select(g => g.First());
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
3

LINQ Distinct admits a IEqualityComparer<T> as parameter. Choosing this way, you may implement your own IEqualityComparer like this:

class ItemEqualityComparer : IEqualityComparer<Item>
{

    public bool Equals(Item i1, Item i2) 
    {
        if (i1.ID == i2.ID && i1.Name == i2.Name && 
           (i1.DrugCode1 == i2.DrugCode1 || i1.DrugCode1 == i2.DrugCode2 ||    
            i1.DrugCode2 == i2.DrugCode1 ))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int  GetHashCode(Item obj)
    {
        int hash = 13;
        int min = Math.Min(obj.DrugCode1, obj.DrugCode2);
        int max = Math.Max(obj.DrugCode1, obj.DrugCode2);
        hash = (hash * 7) + min;
        hash = (hash * 7) + max;
        return hash;
    }  
}

Now you can use it:

var cleanList = listOfItems.Distinct(new ItemEqualityComparer());

It's a little bit longer than a Lambda Expression but it's clean, simple and re-usable.

Please, check the class name (Items should be Item).

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
Francesco De Lisi
  • 1,493
  • 8
  • 20
0

Enumerable.Distinct has an overload that takes a custom IEqualityComparer parameter. Pass in a function that treats two items as equal if their drug codes match in either order.

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93
0

You can write an IEqaulityComparer and then use it with Distinct

class ItemEuqalityComprer : IEqualityComparer<Item>
{
    public bool Equals(Item x, Item y)
    {
        return x.DrugCode1 == y.DrugCode2
               && x.DrugCode2 == y.DrugCode1;
    }

    public int GetHashCode(Item obj)
    {
        return obj.Id == null ? 0 : obj.Id.GetHashCode();
    }
}

The usage with Distinct:

        var item1 = new Item {DrugCode1 = "2", DrugCode2 = "3"};
        var item2 = new Item {DrugCode1 = "3", DrugCode2 = "2"};
        var item3 = new Item { DrugCode1 = "3", DrugCode2 = "4" };
        var items = new[] {item1, item2, item3};

        var distincts = items.Distinct(new ItemEuqalityComprer());
wolfovercats
  • 490
  • 5
  • 11