繁体   English   中英

检查一个列表是否按顺序包含另一个列表中的所有项目

[英]Check if one list contains all items from another list in order

如何确定列表 A 是否以相同的顺序包含列表 B 中的所有元素?

列表 A 可以包含列表 B 没有的其他元素,但必须按照列表 B 的顺序包含列表 B 的所有元素。


示例 1列表 A..., 4, 0, 6结尾):

List A:    List B:
5          2
9          3
2          4
3
4
0
6

这应该返回True


示例 2列表 A..., 0, 4 , 6结尾):

List A:    List B:
5          2
9          3
2          4
3
0
4
6

这应该返回False


从 JonSkeet找到了这个答案,以查看列表 A 是否包含列表 B 中的所有元素,但这并不要求它们的顺序相同。

这需要ListA每个部分并将其与ListBSequenceEqual进行比较:

bool containsSameSequence = ListA
    .Where((item, index) => index <= ListA.Count - ListB.Count)
    .Select((item, index) => ListA.Skip(index).Take(ListB.Count))
    .Any(part => part.SequenceEqual(ListB));

演示

它在第一个匹配序列上返回true

这是一个快速的方法:

var equal = listA.Count - listB.Count < 0 
    ? false 
    : Enumerable.Range(0, listA.Count - listB.Count).Any(i => 
      listA.Skip(i).Take(listB.Count).SequenceEqual(listB));

但是,我更喜欢使用这样的扩展方法:

public static bool ContainsSequence<T>(this IEnumerable<T> outer, 
                                       IEnumerable<T> inner)
{
    var innerCount = inner.Count();
    for(int i = 0; i < outer.Count() - innerCount; i++)
    {
        if(outer.Skip(i).Take(innerCount).SequenceEqual(inner))
            return true;
    }

    return false;
 }

你可以这样称呼它:

var equals = listA.ContainsSequence(listB);

这是特定于List<T>的相同扩展方法的更有效版本:

public static bool ContainsSequence<T>(this List<T> outer, List<T> inner)
{
    var innerCount = inner.Count;

    for (int i = 0; i < outer.Count - innerCount; i++)
    {
        bool isMatch = true;
        for (int x = 0; x < innerCount; x++)
        {
            if (!outer[i + x].Equals(inner[x]))
            {
                isMatch = false;
                break;
            }
        }

        if (isMatch) return true;
    }

    return false;
}

使用String.Join()将 ListA 元素连接在一起。 然后再次使用它将 ListB 元素连接在一起。 然后使用ConcatListA.IndexOf(ConcatListB)

我认为我的版本效率更高。

public static class CollectionExtension
{
    public static bool SequenceContain<T>(this IEnumerable<T> target, IEnumerable<T> that)
    {
        var targetEnumerater = target.GetEnumerator();
        var thatEnumerater = that.GetEnumerator();
        var thatHasValue = thatEnumerater.MoveNext();
        var targetHasValue = targetEnumerater.MoveNext();
        var matchCount = 0;
        try
        {
            while (thatHasValue && targetHasValue)
            {
                if (!EqualityComparer<T>.Default.Equals(targetEnumerater.Current, thatEnumerater.Current))
                {
                    if (matchCount > 0)
                    {
                        thatEnumerater.Reset();
                        thatEnumerater.MoveNext();
                        matchCount = 0;
                    }
                    targetHasValue = targetEnumerater.MoveNext();
                    continue;
                }
                targetHasValue = targetEnumerater.MoveNext();
                thatHasValue = thatEnumerater.MoveNext();
                matchCount++;
            }
            return matchCount == that.Count();
        }
        finally
        {
            thatEnumerater.Dispose();
            targetEnumerater.Dispose();
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM