0

I have a C# class that contains 2 strings, orderNumber and trackingNumber. I created a List of this class and put data into it. I need to remove any duplicate where the orderNumber and trackingNumber are both duplicates. Sometimes the class might contain a duplicate orderNumber but the trackingNumbers are different so I need to keep both.

Thanks, Andrew

AWooster
  • 105
  • 3
  • 9
  • Do you only remove "duplicates" that have both order and tracking the same in the same object? – Hogan Feb 08 '16 at 17:07
  • 2
    Possible duplicate of [Remove duplicates in the list using linq](http://stackoverflow.com/questions/1606679/remove-duplicates-in-the-list-using-linq) – Hogan Feb 08 '16 at 17:08
  • Would an option be to check to see whether the orderNumber and trackingNumber that you want to add to the list already exists? Would be a whole lot easier. – Danny Goodall Feb 08 '16 at 17:12
  • 1
    @DannyGoodall that would be much better actually, that way I limit the amount of data loaded – AWooster Feb 08 '16 at 17:14
  • @AWooster glad I could help. I have had the same sort of problem before so if you need any more help, just let me know :) – Danny Goodall Feb 08 '16 at 17:15
  • @DannyGoodall how would I check to see if both fields exist in the list before adding the new item to the list? – AWooster Feb 08 '16 at 17:16

3 Answers3

3

You could concatenate these strings and then select based on the concatenated string.

List<Item> list = new List<Item>();
Item[] result = list.GroupBy(x => new {x.trackingNumber, x.orderNumber}).Select(x => x.First()).ToArray();

This should work fairly well if you aren't dealing with billions of entries.

Igor Ševo
  • 5,459
  • 3
  • 35
  • 80
  • there are at least 150,000 items in the list – AWooster Feb 08 '16 at 17:28
  • 1
    This is a bad idea because the pair of "ABC" and "DEF" would be a duplicate of "AB" and "CDEF". If you want to concat the strings you need a separator between them that is guaranteed to not be in the strings. Further if you already have a `Tuple` you can just group by that. – juharr Feb 08 '16 at 18:01
  • @juharr I edited the answer. I don't see the reason for the downvote. – Igor Ševo Feb 08 '16 at 23:09
  • you can try to replace `x.trackingNumber + separator + x.orderNumber` with `new { x.trackingNumber, x.orderNumber }` – alex.b Feb 08 '16 at 23:11
0

I think you can do it like this. I assume that Entity class contains OrderNumber and TrackingNumber properties. You can replace it with your original class name.

public class EntityList : List<Entity>
{

    public void Add(Entity entity)
    {

        if (this.Any(n => n.OrderNumber == entity.OrderNumber && n.TrackingNumber == entity.TrackingNumber))
            return;

        base.Add(entity);

    }

}

and the usage :

        var entity1 = new Entity
        {
            OrderNumber = "1",
            TrackingNumber = "100"
        };
        var entity2 = new Entity
        {
            OrderNumber = "2",
            TrackingNumber = "101"
        };
        var entity3 = new Entity
        {
            OrderNumber = "1",
            TrackingNumber = "100"
        };


        var list = new EntityList();

        list.Add(entity1);
        list.Add(entity1);
        list.Add(entity3);

        Console.WriteLine("Count : " + list.Count);
calynr
  • 1,264
  • 1
  • 11
  • 23
0

Let's say for example this is your class:

private class Foo
{
    public readonly string trackingNumber;
    public readonly string orderNumber;

    public Foo(string trackingNumber, string orderNumber)
    {
        this.trackingNumber = trackingNumber;
        this.orderNumber = orderNumber;
    }
}

Getting unique items by trackingNumber and orderNumber can be achieved by leveraging Distinct method passing appropriate comparer:

    private class ByTrackingNumberAndOrderComparer : IEqualityComparer<Foo>
    {
        public bool Equals(Foo x, Foo y)
        {
            return string.Equals(x.trackingNumber, y.trackingNumber)
                && string.Equals(x.orderNumber, y.orderNumber);
        }

        public int GetHashCode(Foo obj)
        {
            return (obj.trackingNumber == null ? 0 : obj.trackingNumber.GetHashCode())
                ^ 397 ^ (obj.orderNumber == null ? 0 : obj.orderNumber.GetHashCode());
        }
    }

Usage:

Foo[] foos = Generate(150000);
Foo[] distinct = foos.Distinct(new ByTrackingNumberAndOrderComparer()).ToArray();
alex.b
  • 4,547
  • 1
  • 31
  • 52