【问题标题】:Quick way to compare arrays with LINQ使用 LINQ 比较数组的快速方法
【发布时间】:2018-02-06 17:41:43
【问题描述】:

有没有办法在 LINQ 中编写短代码来检查一个数组是否是另一个数组的子序列并遵守顺序?

例如(伪代码):

var masterList = new double[] {0,1,2,3,4};
var lst1 = new double[] {0,1,2,3};
var lst2 = new double[] {0,1,3,4};
var lst3 = new double[] {2,3,4};
var lst4 = new double[] {3,4};
var lst5 = new double[] {4,3};

bool isSubseq1 = lst1.Compare(masterList); // true
bool isSubseq2 = lst2.Compare(masterList); // false
bool isSubseq3 = lst3.Compare(masterList); // true
bool isSubseq4 = lst4.Compare(masterList); // true
bool isSubseq5 = lst5.Compare(masterList); // false

编辑:

bool isSubseq = !lst5.Except(masterList).Any(); // returns true, but I want to return false

编辑2: 例 2:

var masterList = new double[] {0,1,2,3,4,4,4,5,6,6,8,8};
var lst1 = new double[] {0,1,2,3};
var lst2 = new double[] {0,3,4};
var lst3 = new double[] {4,4,4};
var lst4 = new double[] {6,6,8,8};
var lst5 = new double[] {5,4,4,4,3};
var lst6 = new double[] {9,9};

bool isSubseq1 = lst1.Compare(masterList); // true
bool isSubseq2 = lst2.Compare(masterList); // false
bool isSubseq3 = lst3.Compare(masterList); // true
bool isSubseq4 = lst4.Compare(masterList); // true
bool isSubseq5 = lst5.Compare(masterList); // false
bool isSubseq6 = lst6.Compare(masterList); // false

是的,我可以编写自己的方法,但这不是我要求的。我将接受嵌套查询。

【问题讨论】:

标签: c# arrays linq


【解决方案1】:

您可以编写自己的方法来执行此操作。我把这个做成了扩展方法:

public static class Extensions
{
    public static bool IsSubsequencetOf<T>(this T[] subset, T[] items)
    {
        if (subset.Length < 1)
            return true;
        if (items.Length < 1)
            return false;

        for (int itemsIndex = 0; itemsIndex <= items.Length - subset.Length; ++itemsIndex)
        {
            if (items[itemsIndex].Equals(subset[0])) // Found a potential start of the subset
            {
                bool isMatch = true;
                int itemsIndexInner = itemsIndex + 1;
                for (int subsetIndex = 1; itemsIndexInner < items.Length && subsetIndex < subset.Length; ++subsetIndex)
                {
                    if (!items[itemsIndexInner].Equals(subset[subsetIndex]))
                    {
                        isMatch = false;
                        break;
                    }

                    itemsIndexInner++;
                }

                if (isMatch)
                    return true;
            }
        }

        return false;
    }
}

你会这样使用它:

bool isSubsequence1 = lst1.IsSubsequencetOf(masterList);

【讨论】:

    【解决方案2】:

    这是另一个相同的实现:

    public static class LinqEx
    {
        public static bool IsSubsequenceOf<T>(
            this IEnumerable<T> subSequence, 
            IEnumerable<T> sequence) where T : IEquatable<T>
        {
            var subSequenceIterator = subSequence.GetEnumerator();
            if (!subSequenceIterator.MoveNext()) return true;
            var started = false;
            foreach (var superitem in sequence)
            {
                if (superitem.Equals(subSequenceIterator.Current))
                {
                    started = true;
                    if (!subSequenceIterator.MoveNext()) return true;
                }
                else if (started)
                {
                    return false;
                }
            }
            return false;
        }
    }
    

    ...查看您的数据:

    bool isSubset1 = lst1.IsSubsequenceOf(masterList); // true
    bool isSubset2 = lst2.IsSubsequenceOf(masterList); // false
    bool isSubset3 = lst3.IsSubsequenceOf(masterList); // true
    bool isSubset4 = lst4.IsSubsequenceOf(masterList); // true
    bool isSubset5 = lst5.IsSubsequenceOf(masterList); // false
    

    是的。

    【讨论】:

      【解决方案3】:

      基于 Nacho 的 idea,这是我的解决方案(不理想,但我暂时采用):

          [TestCase(new int[] { 0, 1, 2, 3 }, true)]
          [TestCase(new int[] { 0, 3, 4 }, false)]
          [TestCase(new int[] { 4, 4, 4 }, true)]
          [TestCase(new int[] { 6, 6, 8, 8 }, true)]
          [TestCase(new int[] { 5, 4, 4, 4, 3 }, false)]
          [TestCase(new int[] { 9, 9 }, false)]
          [TestCase(new int[] { 0, 2 }, false)]
          [TestCase(new int[] { }, false)] // bug: SkipWhile skips all master's items, so master[] { } == sub[] { } is true;
          public void MethodToTest(int[] sub, bool expected)
          {
              var master = new int[] { 0, 1, 2, 3, 4, 4, 4, 5, 6, 6, 8, 8 };
      
              var result = master.SkipWhile((x, i) => !master.Skip(i).Take(sub.Length).SequenceEqual(sub))
                  .Take(sub.Length).SequenceEqual(sub);
      
              Assert.AreEqual(expected, result);
          }
      

      编辑:修复空数组问题:

          var result = master.SkipWhile((x, i) => !master.Skip(i).Take(sub.Length).SequenceEqual(sub))
              .Take(sub.Length).DefaultIfEmpty().SequenceEqual(sub);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 1970-01-01
        • 2012-03-09
        • 1970-01-01
        相关资源
        最近更新 更多