The opposite of Intersect()

134,249

Solution 1

As stated, if you want to get 4 as the result, you can do like this:

var nonintersect = array2.Except(array1);

If you want the real non-intersection (also both 1 and 4), then this should do the trick:

var nonintersect = array1.Except(array2).Union( array2.Except(array1));

This will not be the most performant solution, but for small lists it should work just fine.

Solution 2

You can use

a.Except(b).Union(b.Except(a));

Or you can use

var difference = new HashSet(a);
difference.SymmetricExceptWith(b);

Solution 3

This code enumerates each sequence only once and uses Select(x => x) to hide the result to get a clean Linq-style extension method. Since it uses HashSet<T> its runtime is O(n + m) if the hashes are well distributed. Duplicate elements in either list are omitted.

public static IEnumerable<T> SymmetricExcept<T>(this IEnumerable<T> seq1,
    IEnumerable<T> seq2)
{
    HashSet<T> hashSet = new HashSet<T>(seq1);
    hashSet.SymmetricExceptWith(seq2);
    return hashSet.Select(x => x);
}

Solution 4

I think you might be looking for Except:

The Except operator produces the set difference between two sequences. It will only return elements in the first sequence that don't appear in the second. You can optionally provide your own equality comparison function.

Check out this link, this link, or Google, for more information.

Solution 5

array1.NonIntersect(array2);

Nonintersect such operator is not present in Linq you should do

except -> union -> except

a.except(b).union(b.Except(a));
Share:
134,249

Related videos on Youtube

Peter Bridger
Author by

Peter Bridger

Technical Architect at Zone (https://www.thisiszone.com/) instilling the benefits of TDD and SOLID within the teams I run and using Scrum and a Continuous Delivery pipeline to continuously deliver high quality software

Updated on September 21, 2020

Comments

  • Peter Bridger
    Peter Bridger over 3 years

    Intersect can be used to find matches between two collections, like so:

    // Assign two arrays.
    int[] array1 = { 1, 2, 3 };
    int[] array2 = { 2, 3, 4 };
    // Call Intersect extension method.
    var intersect = array1.Intersect(array2);
    // Write intersection to screen.
    foreach (int value in intersect)
    {
        Console.WriteLine(value); // Output: 2, 3
    }
    

    However what I'd like to achieve is the opposite, I'd like to list items from one collection that are missing from the other:

    // Assign two arrays.
    int[] array1 = { 1, 2, 3 };
    int[] array2 = { 2, 3, 4 };
    // Call "NonIntersect" extension method.
    var intersect = array1.NonIntersect(array2); // I've made up the NonIntersect method
    // Write intersection to screen.
    foreach (int value in intersect)
    {
        Console.WriteLine(value); // Output: 4
    }
    
    • Øyvind Bråthen
      Øyvind Bråthen about 13 years
      please confirm if you want 4 as the output, or 1 and 4
    • Peter Bridger
      Peter Bridger about 13 years
      @oyvind-knobloch-brathen Yes, I would only like 4
    • Mike T
      Mike T almost 12 years
      As a side note, this type of set is called a Symmetric Difference.
    • rtorres
      rtorres almost 10 years
      Technically speaking, a Symmetric Difference would result into [1, 4]. Since Peter wanted just the elements in array2 that are not in array1 (i.e., 4), that's called a Relative Complement (aka Set-Theoretic Difference)
  • Peter Bridger
    Peter Bridger about 13 years
    Interesting use of SymmetricExceptWith(), I wouldn't have thought of that approach
  • shanabus
    shanabus over 12 years
    what would be a better performing solution? Thanks!
  • Øyvind Bråthen
    Øyvind Bråthen over 12 years
    You can probably do it faster by using two nested for loops, but the code will be way dirtier than this. Counting readability into this also, I would clearly use this variant as it's very easy to read.
  • Ash Clarke
    Ash Clarke about 11 years
    SymmetricExceptWith is probably my favourite method.
  • Dan
    Dan about 11 years
    I compared the two in a real application where I had a couple lists of about 125 strings in each of them. Using the first approach is actually faster for lists of that size, though its mostly insignificant as both approaches where under half a millisecond.
  • Dwighte
    Dwighte almost 11 years
    Just a sideline point to add, If you have: int[] before = { 1, 2, 3 }; int[] after = { 2, 3, 3, 4 }; and you try to use Except to find what's been added to 'after' since 'before': var diff = after.Except(before); 'diff' contains 4, not 3,4. i.e. watch out for duplicate elements giving you unexpected results
  • Drew Noakes
    Drew Noakes almost 9 years
    Would be nice if the BCL had a Linq extension method for this. It seems like an omission.
  • Colin
    Colin almost 7 years
    Someone benchmarked SymmetricExceptWith and found it much faster: skylark-software.com/2011/07/linq-and-set-notation.html
  • LBW
    LBW about 6 years
    Would this perform better? array1.AddRange(array2.Except(array1));
  • amuliar
    amuliar over 5 years
    Intersection of sets == A∪B\A∩B
  • TheHunter Shergill
    TheHunter Shergill over 2 years
    @ØyvindBråthen thank you it helped a lot.
  • Filimindji
    Filimindji over 2 years
    I like the extension method, but I'm not sure about the .Select(x => x). Don't you think it add some unnecessary overhead ?