user888734
user888734

Reputation: 3897

How to match a sequence in a List with LINQ?

Is it possible using LINQ to test for a match of a sequence of list items? e.g.

var masterList = new List<string>{"fox", "jumps", "dog"};
var childList1 = new List<string>{"fox", "jumps"};
var childList2 = new List<string>{"fox", "dog"};

I'd like to write something such that looking for childList1 in masterList is true, but childList2 is false, because there's something in between.

EDIT: {"jumps", "dog"} would also match.

Upvotes: 0

Views: 1805

Answers (3)

D Stanley
D Stanley

Reputation: 152566

My answer is similar to Andrei's but may be faster since it looks for the first item in the parent list to limit the number of searches:

public bool SubsequenceEquals<T>(IEnumerable<T> masterList, IEnumerable<T> childList)
{
    // find all indexes 
    var matches = masterList.Select((s, i) => new {s, i})
                            .Where(m => m.s.Equals(childList.First()))
                            .Select (m => m.i);

    return matches.Any(m => Enumerable.SequenceEqual(childList, masterList
                                                           .Skip(m)
                                                           .Take(childList.Count())));
}

Upvotes: 1

Andrei
Andrei

Reputation: 1061

If exact sequence of elements is important try something like:

public static bool ListContains<T>(List<T> source, List<T> search)
{
    if (search.Count > source.Count)
        return false;

    return Enumerable.Range(0, source.Count - search.Count + 1)
        .Select(a => source.Skip(a).Take(search.Count))
        .Any(a => a.SequenceEqual(search));
}

public static void Main(string[] args)
{
    var masterList = new List<string> { "fox", "jumps", "dog" };
    var childList1 = new List<string> { "fox", "jumps" };
    var childList2 = new List<string> { "fox", "dog" };

    Console.WriteLine(ListContains(masterList, childList1));
    Console.WriteLine(ListContains(masterList, childList2));
}

Upvotes: 1

evanmcdonnal
evanmcdonnal

Reputation: 48096

There is another question that has a working answer; Check whether an array is a subset of another

bool isSubest = !childList1.Except(masterList).Any();

will do it for you. You could also do

  if (childList1.Except(masterList).Count > 0)
      // items in child not in master
  else
       //child is a subest of master

Upvotes: 0

Related Questions