kobosh
kobosh

Reputation: 467

Find common items in list of lists of strings

Hi I have allLists that contains lists of string I want to find common items among these string lists i have tried

var intersection = allLists
  .Skip(1)
  .Aggregate(
  new HashSet<string>(allLists.First()),
  (h, e) => { h.IntersectWith(e); return h);`

and also intersection ( hard code lists by index) all of them did not work when I tried

var inter = allLists[0].Intersect(allLists[1]).Intersect(allLists[2])
     .Intersect(allLists[3]).ToList();

foreach ( string s in inter) Debug.WriteLine(s+"\n ");

So how am I going to do this dynamically and get common string items in the lists; is there a way to avoid Linq?

Upvotes: 3

Views: 2032

Answers (2)

t3chb0t
t3chb0t

Reputation: 18665

I'd do it like this:

class Program
{
    static void Main(string[] args)
    {
        List<string>[] stringLists = new List<string>[] 
        { 
            new List<string>(){ "a", "b", "c" },
            new List<string>(){ "d", "b", "c" },
            new List<string>(){ "a", "e", "c" }
        };

        // Will contian only 'c' because it's the only common item in all three groups.
        var commonItems = 
            stringLists
            .SelectMany(list => list)
            .GroupBy(item => item)
            .Select(group => new { Count = group.Count(), Item = group.Key })
            .Where(item => item.Count == stringLists.Length);

        foreach (var item in commonItems)
        {
            Console.WriteLine(String.Format("Item: {0}, Count: {1}", item.Item, item.Count));
        }
        Console.ReadKey();
    }
}

An item is a common item if it occurs in all groups hence the condition that its count must be equal to the number of groups:

.Where(item => item.Count == stringLists.Length)

EDIT:

I should have used the HashSet like in the question. For lists you can replace the SelectMany line with this one:

.SelectMany(list => list.Distinct())

Upvotes: 0

Enigmativity
Enigmativity

Reputation: 117064

Isn't this the easiest way?

var stringLists = new List<string>[] 
    { 
        new List<string>(){ "a", "b", "c" },
        new List<string>(){ "d", "b", "c" },
        new List<string>(){ "a", "e", "c" }
    };

var commonElements =
    stringLists
        .Aggregate((xs, ys) => xs.Intersect(ys).ToList());

I get a list with just "c" in it.

This also handles the case if elements within each list can be repeated.

Upvotes: 2

Related Questions