find common items across multiple lists in C#

Viewed 85389

I have two generic list :

List<string> TestList1 = new List<string>();
List<string> TestList2 = new List<string>();
TestList1.Add("1");
TestList1.Add("2");
TestList1.Add("3");
TestList2.Add("3");
TestList2.Add("4");
TestList2.Add("5");

What is the fastest way to find common items across these lists?

8 Answers

Using HashSet for fast lookup. Here is the solution:

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        List<int> list1 = new List<int> {1, 2, 3, 4, 5, 6 };
        List<int> list2 = new List<int> {1, 2, 3 };
        List<int> list3 = new List<int> {1, 2 };

        var lists = new IEnumerable<int>[] {list1, list2, list3 };

        var commons = GetCommonItems(lists);
        Console.WriteLine("Common integers:");
        foreach (var c in commons)
            Console.WriteLine(c);

    }

    static IEnumerable<T> GetCommonItems<T>(IEnumerable<T>[] lists)
    {
        HashSet<T> hs = new HashSet<T>(lists.First());
        for (int i = 1; i < lists.Length; i++)
            hs.IntersectWith(lists[i]);
        return hs;
    }
}

Following the lead of @logicnp on counting the number of lists containing each member, once you have your list of lists, it's pretty much one line of code:

List<int> l1, l2, l3, cmn;
List<List<int>> all;

l1 = new List<int>() { 1, 2, 3, 4, 5 };
l2 = new List<int>() { 1, 2, 3, 4 };
l3 = new List<int>() { 1, 2, 3 };
all = new List<List<int>>() { l1, l2, l3 };

cmn = all.SelectMany(x => x).Distinct()
      .Where(x => all .Select(y => (y.Contains(x) ? 1 : 0))
      .Sum() == all.Count).ToList();

Or, if you prefer:

public static List<T> FindCommon<T>(IEnumerable<List<T>> Lists)
{
  return Lists.SelectMany(x => x).Distinct()
      .Where(x => Lists.Select(y => (y.Contains(x) ? 1 : 0))
      .Sum() == Lists.Count()).ToList();
}
Related