【问题标题】:Check if array contains exact same sequence as other array检查数组是否包含与其他数组完全相同的序列
【发布时间】:2016-10-26 17:48:44
【问题描述】:

我有一个问题,我需要检查某个数组是否是更大数组的一部分,这很容易,但我需要检查更大数组是否包含完全相同的序列。例如

int[] greaterArray = {8, 3, 4, 5, 9, 12, 6 ... n - elements}
int[] lesserArray = {3, 4, 5}

现在我需要知道较小的数组是否是该数组的一部分但具有相同的序列,因此它在较大的数组中包含彼此相邻的 3、4、5。

我试过了:

var exists = greaterArray.Intersect(lesserArray).Any();

但是如果较小数组的任何元素存在于较大数组中,它会返回信息,而不是确切的顺序。有什么想法吗?

【问题讨论】:

  • @JaydipJ 这个答案不涉及子集。
  • 这只是您在问题标题中所说的内容检查数组是否包含与其他数组完全相同的序列
  • 不是我的问题标题。尽管如此,事实仍然存在;它没有回答问题。
  • 绝对不是@JaydipJ。他在问子序列不是同一个数组

标签: c# arrays


【解决方案1】:
    int[] greaterArray = {8, 3, 4, 5, 9, 12, 6};
    int[] lesserArray = { 3, 4, 5 };
    bool sequenceFound = false;

    for (int i = 0; i <= greaterArray.Length - lesserArray.Length; i++)
    {
        if (greaterArray.Skip(i).Take(lesserArray.Length).SequenceEqual(lesserArray))
        {
            sequenceFound = true;
            break;
        }
    }

    if (sequenceFound)
    {
        //sequence found
    }
    else
    {
        //sequence not found
    }

使用上面的代码。它从greaterArray 中获取长度等于lesserArray 长度的多个子序列,并将其与lesserArray 匹配。

【讨论】:

【解决方案2】:

更通用一点,不使用 LINQ:

int[] greaterArray = {8, 2, 4, 5, 9, 12, 3, 4, 5};
int[] lesserArray = {3, 4, 5};
for (int i = 0; i <= greaterArray.Length - lesserArray.Length; i++)
            {
                var sub = greaterArray.SubArray(i, lesserArray.Length);
                if (Enumerable.SequenceEqual(sub, lesserArray))
                {
                    Console.WriteLine("Equals!");
                }
            }

还有这个用来获取子数组的工具:

public static T[] SubArray<T>(this T[] data, int index, int length)
        {
            T[] result = new T[length];
            Array.Copy(data, index, result, 0, length);
            return result;
        }

【讨论】:

    【解决方案3】:

    这应该做你的工作

    int[] grtarr = { 8, 3, 4, 5, 9, 12, 6 };
    int[] lsarr = { 3, 4, 5 };
    
    List<int> lstGrtArr = grtarr.ToList();
    List<int> lstLsrArr = lsarr.ToList();
    
    bool sequenceMatch = false;
    
    for (int i = 0; i < grtarr.Count(); i++)
    {
        if (lstGrtArr.Where(x => lstGrtArr.IndexOf(x) >= i).Take(lstLsrArr.Count()).SequenceEqual(lstLsrArr))
        {
            sequenceMatch = true;
            break;
        }
    }
    
    if(sequenceMatch)
    {
        //Do Something
    }
    
    【解决方案4】:
        static bool isPrefix(int[] source, int start_pos, int[] prefix)
        {
            bool result = start_pos + prefix.Length <= source.Length;
            for (int i = 0; result && i < prefix.Length; ++i, ++start_pos)
                result = source[start_pos] == prefix[i];
            return result;
        }
        static bool Contains(int[] source, int[] prefix)
        {
            bool result = false;
            for (int i = 0; !result && i < source.Length; ++i)
                result = source[i] == prefix[0] ? isPrefix(source, i, prefix) : false;
            return result;
        }
    

    【讨论】:

      【解决方案5】:

      使用这段代码:

      public bool ArraysEqual<T>(T[] a1, T[] a2)
      {
          if (ReferenceEquals(a1,a2))
              return true;
      
          if (a1 == null || a2 == null)
              return false;
      
          if (a1.Length != a2.Length)
              return false;
      
          EqualityComparer<T> comparer = EqualityComparer<T>.Default;
          for (int i = 0; i < a1.Length; i++)
          {
              if (!comparer.Equals(a1[i], a2[i])) return false;
          }
          return true;
      }
      

      或者如果你想使用 Linq 并且不太关心性能,最简单的方法是:

      var arrays_are_the_same = Enumerable.SequenceEqual(a1, a2);
      

      【讨论】:

      • 两种解决方案的性能有何不同?它不像你的 ArraysEqual&lt;T&gt; 包含一些加速魔法(虽然不是我的 -1)。
      • 这不能回答问题。 OP 询问 lesserArray 是否是 greaterArray 的子集,且元素的顺序相同。
      猜你喜欢
      • 1970-01-01
      • 2018-01-15
      • 2021-02-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多