考虑一下我们有这三个列表:
List<string> l1= new List<string>(){"A","B","C"};
List<string> l2= new List<string>(){"A","C","B"};
List<string> l3= new List<string>(){"B","C"};
我需要LINQ查询,其中l1包含l3但l2不包含。
答案 0 :(得分:6)
要尊重订单并说明您必须枚举序列的可能重复元素,一种方法是检查源枚举中的每个起始位置(如果其他序列从此处开始) ,例如使用扩展方法:
public static bool ContainsSequence<T>(this IEnumerable<T> source,
IEnumerable<T> other)
{
int count = other.Count();
while (source.Any())
{
if (source.Take(count).SequenceEqual(other))
return true;
source = source.Skip(1);
}
return false;
}
请注意,这将是O(n 2 ),因为最糟糕的情况是,您已完全枚举other
集合中每个项目的source
枚举。
现在你可以做到:
List<string> l1 = new List<string>() { "A", "B", "C" };
List<string> l2 = new List<string>() { "A", "C", "B" };
List<string> l3 = new List<string>() { "B", "C" };
bool l1ContainsL2 = l1.ContainsSequence(l2); //returns false
bool l1ContainsL3 = l1.ContainsSequence(l3); //returns true
答案 1 :(得分:2)
应该是:
l1.Intersect(l3).Except(l2);
注意:
根据l2和l3的大小,相反的顺序可能更有效
根据您的特定值,不会返回任何内容,因为l1中没有任何内容不在l3中。
答案 2 :(得分:2)
Exclaimer:正如BrokenGlass所指出的,目前还不清楚列表包含另一个列表是什么意思。在这里,我允许包含序列在所包含序列的项目之间有其他项目。
快速打字,效率不高:
bool l1contains = l1.Where(x => l3.Contains(x)).ToList().SequenceEqual(l3);
bool l2contains = l2.Where(x => l3.Contains(x)).ToList().SequenceEqual(l3);
效率更高 - 尽可能高效,在O(m + n)中运行,其中m,n是列表的长度。
private static bool ContainsOrdered<T>(IEnumerable<T> containing, IEnumerable<T> contained)
{
var e1 = containing.GetEnumerator();
var e2 = contained.GetEnumerator();
bool hasmore1 = e1.MoveNext();
bool hasmore2 = e2.MoveNext();
while (hasmore1 && hasmore2)
{
while (hasmore1 && !e1.Current.Equals(e2.Current))
hasmore1 = e1.MoveNext();
if (hasmore1) // Currents are equal
{
hasmore1 = e1.MoveNext();
hasmore2 = e2.MoveNext();
}
}
return !hasmore2;
}
bool contains1 = ContainsOrdered(l1, l3);
bool contains2 = ContainsOrdered(l2, l3);