Linq查询列表包含具有相同顺序的列表

时间:2012-02-07 21:05:34

标签: c# linq

考虑一下我们有这三个列表:

    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不包含。

3 个答案:

答案 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);