【问题标题】:How to check if list contains another list in same order如何检查列表是否包含另一个相同顺序的列表
【发布时间】:2016-01-04 16:16:30
【问题描述】:

在 C# 中是否有任何简单的方法来检查列表是否包含另一个列表? 这是示例, 我有:

var list1 = new List<int>() {1, 2, 3, 4, 5, 6,}; 第二个 var list2 = new List<int>() {5, 6};

这个列表是第一个列表的一部分,所以它应该返回 true。

var list1 = new List<int>() {1, 2, 3, 4, 5, 6,};var list3 = new List<int>() {1, 3}; 应该返回 false。

这不是关于检查第一个列表中的所有元素是否存在于第二个列表中,而是关于顺序。它必须具有相同的顺序。

【问题讨论】:

  • 你想要一个通用的解决方案还是只针对整数列表?
  • 你试过什么?你写了什么代码?您进行了哪些研究?
  • 你的意思是包含另一个相同顺序的列表吗?
  • 如果您的问题包含可以使用的有效代码,我会很好。
  • 是的,现在我只需要它用于 intigers。现在我试图找出是否已经有任何现有的解决方案来解决这个问题。是的,顺序很重要

标签: c# list


【解决方案1】:

这对我有用:

public bool ContainsSubsequence<T>(List<T> sequence, List<T> subsequence)
{
    return
        Enumerable
            .Range(0, sequence.Count - subsequence.Count + 1)
            .Any(n => sequence.Skip(n).Take(subsequence.Count).SequenceEqual(subsequence));
}

此代码使用Enumerable.Range 遍历sequence 中可能与subsequence 相同的每个可能的起点,并检查sequence 在此位置的大小是否与subsequence 相同实际上等于subsequence

所以对于这段代码:

var list1 = new List<int>() { 1, 2, 3, 4, 5, 6, };
var list2 = new List<int>() { 5, 6, };
var list3 = new List<int>() { 1, 3, };

Console.WriteLine(ContainsSubsequence(list1, list2));
Console.WriteLine(ContainsSubsequence(list1, list3));

我明白了:

True
False

【讨论】:

  • 使用var list3 = new List&lt;int&gt;() { 1, 2, }; 它应该返回true 但它返回false
  • @user2946329 - 我的代码确实有错误,但我修复了它。 { 1, 2 } 现在可以正常工作了。
  • @Enigmativity .. 是的。现在它变成了一个很好的综合解决方案。 +1。
  • 我对此进行了一点测试,如果 sequence.Count 小于 subsequence.Count,它会引发异常。所以在这个方法的开头加上“if”条件是很有必要的。
  • @wgrzesiak147 - 是的,这很公平。我编写代码是为了简洁,而不是健壮性。我通常认为如果代码尽可能简单,就很容易看出代码的意图。但我相信大多数程序员都会理解强化代码的必要性。
【解决方案2】:

感谢@GeorgeVovos 和@Enigmativity 指出第一个解决方案中的问题。

public static bool HasSubSequence(List<int> main, List<int> query)
{
    var startIndex = main.IndexOf(query.First());
    if (main == null || query == null || startIndex < 0)
        return false;

    while (startIndex >= 0)
    {        
        if (main.Count - startIndex < query.Count)
            return false;
        var nonMatch = false;
        for (int i = 0; i < query.Count; i++)
        {
            if (main[i + startIndex] != query[i])
            {
                main = main.Skip(startIndex + 1).ToList();
                startIndex = main.IndexOf(query.First());
                nonMatch = true;
                break;
            }
        }
        if (!nonMatch)
            return true;
    }
    return false;
}

例子

var l1 = new List<int> { 1, 2, 3, 4, 5 };
var l2 = new List<int> { 4, 5 };
var l3 = new List<int> { 1, 3 };
var l4 = new List<int> { 5, 6 };

var l5 = new List<int> { 1, 2, 3, 2, 5, 6, 2, 4, 8 };
var l6 = new List<int> { 2, 4 };

var test1 = HasSubSequence(l1, l2); //true
var test2 = HasSubSequence(l1, l3); //false
var test3 = HasSubSequence(l1, l4); //false

var test5 = HasSubSequence(l5, l6); //true

【讨论】:

  • 元素的顺序很重要。
  • 你需要用while循环包装你的代码(并稍微修改indexof),因为第二个列表的第一个元素可能在之前存在
  • 如果query.First()出现在main子序列之前,这仍然不起作用。
  • 确实,for 循环也必须更改。列表开始时不会出现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 2023-03-18
  • 2017-01-13
  • 1970-01-01
相关资源
最近更新 更多