16

I'm having trouble preserving the duplicates when comparing two List<T> objects. The goal is to have the duplicates added to a third list, call it list3.

list1 has about 5 items, while list2 has 10 items.

list3 should contain the following: 00T51234, 00T54567, 00T57894

List<string> list1 = new List<string>(){"00T51234", "00T54567", "00T57894",
                     "00T55263", "00T58965"};

List<string> list2 = new List<string>(){"00T59633", "00T52222", "00T57894", 
                     "00T52322", "00T51234", "00T54567", "00T57894", "00T57897",
                     "00T55556", "00T59563"};

List<string> list3 = new List<string>();

I attempted to use Ani's resolution, seen below:

var lookup2 = list2.ToLookup(str => str);

var result = from str in list1
         group str by str into strGroup
         let missingCount 
              = Math.Max(0, strGroup.Count() - lookup2[strGroup.Key].Count())
         from missingStr in strGroup.Take(missingCount)
         select missingStr;

However this solution is not giving me the result that I'm looking for. Any help would be greatly appreciated. Thanks!

Community
  • 1
  • 1
toose121
  • 303
  • 1
  • 2
  • 9

2 Answers2

33

Use Enumerable.Intersect method

List<string> duplicates = list1.Intersect(list2).ToList();
Sachin
  • 40,216
  • 7
  • 90
  • 102
  • And then to finish it off, call `ToList()`. The original poster specifies that the desired result is a third list. – Eric Lippert Jan 15 '14 at 21:09
  • Thank you! This is exactly what i need. Can you confirm whether or not `Intersect` is the opposite of `Except`? – toose121 Jan 15 '14 at 21:24
  • 2
    @toose121 It's not _exactly_ the opposite - `a.Except(b)` will give you the items that are in `a` but not in `b` - it will not give you the items in `b` that are not in `a`. – D Stanley Jan 15 '14 at 21:51
  • I believe the exact opposite would be `a.Union(b).Except(a.Intersect(b))`. – Erik Philips Sep 22 '18 at 22:29
-1

I figured I would throw down a few. It is a few of the examples from above, but I needed more of an inner right join. Check it.

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public class Program
    {
        public static void Main()
        {
            //Intersect
            var listA = new List<string>{"A", "B", "C", "D", "G"};
            var listB = new List<string>{"C", "C", "A", "E", "A", "F", "Q", "Q"};
            var matching = listA.Intersect(listB).ToList();
            Console.WriteLine(matching.Str());
            
            //Right Inner Join
            var query = listA.GroupJoin(listB, a => a, b => b, (a, abList) => abList.ToList());
            Console.WriteLine(query.Str());
            
            //Inner Distinct
            var innerDist = listA.Union(listB);
            Console.WriteLine(innerDist.Str());
            
            //Outter Distinct
            var flippedDupMatch = listB.Union(listA).Except(listB.Intersect(listA));
            Console.WriteLine(flippedDupMatch.Str());
        }
    }
    
    public static class Temp
    {
        public static string Str(this IEnumerable<string> str)
        {
            return str.Count() + " " + string.Join(",", str);
        }
    
        public static string Str(this List<string> str)
        {
            return str.Count() + " " + string.Join(",", str);
        }
    
        public static string Str(this IEnumerable<List<string>> str)
        {
            return str.SelectMany(x => x).ToList().Str();
        }
    }

.netFiddle

DeadlyChambers
  • 5,217
  • 4
  • 44
  • 61