1

I have two generic collections named barcodesSource and barcodesTarget. Both of them are the same type Helper. I want to compare collection named barcodesSource with second one collection base upon property BARCODE and return only data from first collection, which havent corresponding BARCODE in second collection.

Can any one tell me a solution of this?

class Helper
{
    public long BARCODE { get; set; }
    public int ITEM { get; set; }
}


List<Helper> barcodesSource = new List<Helper>();
List<Helper> barcodesTarget = new List<Helper>();

var distinctBarcodes = barcodesSource.Where(a => barcodesTarget.All(b => b.BARCODE != a.BARCODE));
Jenish Rabadiya
  • 6,708
  • 6
  • 33
  • 62

5 Answers5

5

Use Any:

var distinctBarcodes = barcodesSource.Where(a => !barcodesTarget.Any(b => b.BARCODE == a.BARCODE));
Giorgi Nakeuri
  • 35,155
  • 8
  • 47
  • 75
  • 1
    Not sure why is this getting upvoted so much as it produces complexity of `O(N2)` (or close to that) and this is not desirable, and can cause performance issues in case both collections are large. – Fabjan Nov 30 '15 at 09:25
  • @Fabjan, of cource you can order both with O(NlogN) and one pass through will do it, but this is not a CS question. And I know nothing about the data and quantity. In most cases solution provided will work just fine. – Giorgi Nakeuri Nov 30 '15 at 09:32
  • If I use or code, i ll get in Result View Error Function evaluation disabled because a previous function evaluation timed out. You must continue execution to reenable function evaluation. One collection has over 64 000 rows and other around 60 000 rows. – Vladimir Toth Nov 30 '15 at 09:51
  • @VladimirToth, just search for the error in google. Tons of answers here two. – Giorgi Nakeuri Nov 30 '15 at 09:52
1

You can use Join in Lambda Expression to get the same Helper objects.

barcodesSource.Join(barcodesTarget, x=> new {x.BARCODE, x.ITEM}, y=> new {y.BARCODE, y.ITEM}, (x,y)=> x);

You can use this helper method for getting different objects:

public static IEnumerable<TOuter> NotJoin<TOuter, TInner, TKey>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector)
    where TInner : class
    where TOuter : class
{
    IEnumerable<TOuter> results = from o in outer join i in inner on outerKeySelector(o) equals innerKeySelector(i) into joinData from left in joinData.DefaultIfEmpty() where left == null select o;
    return results;
}

barcodesSource.NotJoin(barcodesTarget, x=> new {x.BARCODE, x.ITEM}, y=> new {y.BARCODE, y.ITEM});
Sinan AKYAZICI
  • 3,942
  • 5
  • 35
  • 60
0

You can use LINQ .Except() method and custom Comparer class :

   class Helper
    {
        public string barCode;
    }

    class MyComparer : IEqualityComparer<Helper>
    {
        public bool Equals(Helper x, Helper y)
        {
            return x.barCode == y.barCode;
        }

        public int GetHashCode(Helper obj)
        {
            return obj.GetHashCode();
        }
    }

    class Class1
    {
        static void Main()
        {
            List<Helper> bcs1 = new List<Helper>()
            {
                new Helper() { barCode = "0001" },
                new Helper() { barCode = "0002" },
                new Helper() { barCode = "0003" },
                new Helper() { barCode = "0004" }
            };

            List<Helper> bcs2 = new List<Helper>()
            {
                new Helper() { barCode = "0001" },
                new Helper() { barCode = "0002" },
                new Helper() { barCode = "0003" }
            };

            bcs1 = bcs1.Except(bcs2, new MyComparer()).ToList();

            Console.WriteLine(bcs1.Count);    
            Console.WriteLine(bcs1.First().barCode);

            Console.ReadKey();
        }
    }

Output: 1 0004

Fabjan
  • 13,506
  • 4
  • 25
  • 52
  • Instead of `return base.GetHashCode();` do `return BARCODE.GetHashCode();` as OP is only concerned about the BARCODE value not with respective ITEM value of Helper class. – Jenish Rabadiya Nov 30 '15 at 09:20
  • @JenishRabadiya good point, although OP just wants to get set difference between two collections – Fabjan Nov 30 '15 at 09:22
0

Another set based approach using HashSet<>.Contains:

var barcodes = new HashSet<long>(barcodesTarget.Select(b => b.BARCODE));
var distinctBarcodes = barcodesSource.Where(a => !barcodes.Contains(a.BARCODE));
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
0

One option is to use set operations, i.e.

var result = new HashSet<Helper>(barcodesSource);
result.ExceptWith(barcodesTarget);
Krumelur
  • 31,081
  • 7
  • 77
  • 119