Reputation: 3897
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
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
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
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