【问题标题】:How to search a List(Of Byte) for two values using the Framework?如何使用框架在 List(Of Byte) 中搜索两个值?
【发布时间】:2010-10-14 22:34:07
【问题描述】:

有没有一种方法可以在列表中搜索多个连续值?我查看了 Find 和 IndexOf 但 Find 使用的谓词仅使用当前值,而 IndexOf 仅采用字节参数。

我可以编写自己的解决方案,但我想确定没有解决这个常见问题的可用解决方案。

提前致谢。

【问题讨论】:

    标签: .net search list indexing find


    【解决方案1】:

    说实话,我认为这不是一个特别常见的问题 - 我很确定框架中没有任何内容。

    我怀疑你需要弄清楚你是想要效率还是简单来实现你自己的。一个相当简单的扩展方法版本可能如下所示:

    public static int IndexOf<T>(this IEnumerable<T> source,
                                 T first,
                                 T second)
    {
        IEqualityComparer<T> comparer = EqualityComparer<T>.Default;
    
        // We can only return when we've read source[index+1], so we need
        // to keep one value behind
        int index=-1;
        T prev = default(T);
        foreach (T element in source)
        {
            if (comparer.Equals(first, prev) &&
                comparer.Equals(second, element) &&
                index >= 0) // Avoid edge cases where first=default(T)
            {
                return index;
            }
            index++;
            prev = element;
        }
        return -1;
    }
    

    【讨论】:

    • 这只是因为我们可以在列表或数组中搜索一项看起来很常见,以搜索多个项目。无论如何感谢您的回复,我编写了一个搜索 n 项的通用解决方案。
    【解决方案2】:

    一个想法可能是将您的列表分成连续值的组,然后比较每个值的内容。这是另一个将执行拆分的函数(从 F# 核心库中提取)。

    static IEnumerable<T[]> Windowed<T>(this IEnumerable<T> source, int size)
    {
      if (source == null)
        throw new NullReferenceException();
      if (size <= 0)
        throw new ArgumentOutOfRangeException("size", "The window size must be positive.");
    
      var arr = new T[size];
      var r = size-1;
      var i = 0;
      foreach (T item in source)
      {
        arr[i] = item;
        i = (i+1) % size;
        if (r == 0)
        {
          var res = new T[size];
          for (int j = 0; j < size; j++)
            res[j] = arr[(i+j) % size];
          yield return res;
        }
        else 
          r -= 1;
      }
    }
    

    你可以像这样使用上面的函数:

    var result = Enumerable.Range(1, 10).Windowed(2)
                   .Where(a => a[0] == 3 && a[1] == 4)
                   .First();
    

    【讨论】:

      【解决方案3】:

      这是我自己对问题的解决方案。我喜欢这个方法,因为它可以处理任意数量的项目,是 O(n) 并且非常简单:

          <Extension()> Public Function Find(Of T)(ByVal list As List(Of T), ByVal searchedValue As T(), ByVal startingIndex As Integer) As Integer
          Dim mainIndex As Integer
          Dim searchedIndex As Integer
          Dim result As Integer
      
          result = -1 ' Initialize result
          mainIndex = startingIndex
      
          While mainIndex < list.Count AndAlso result = -1
              If list(mainIndex).Equals(searchedValue(0)) Then
                  searchedIndex = 0
                  While searchedIndex < searchedValue.Length AndAlso (list(mainIndex + searchedIndex).Equals(searchedValue(searchedIndex)))
                      searchedIndex = searchedIndex + 1
                  End While
      
                  If searchedIndex = searchedValue.Length AndAlso list(mainIndex + searchedIndex - 1).Equals(searchedValue(searchedIndex - 1)) Then
                      result = mainIndex
                  End If
              End If
      
              mainIndex = mainIndex + 1
          End While
      
          Return result
      End Function
      

      【讨论】:

      • 不是 O(n)。它是 O(n * m),其中 m 是搜索值的大小。如果您需要在只是 XXXXXXXXXXXXXXXXXXXXX 等字符串中查找 XXXXXXXXXXXXXXXXXY,那么您将进行很多不必要的比较。
      • 我还建议您在找到匹配项后直接从循环中返回。我从来不喜欢为了确保只有一个返回点而使代码更复杂的口头禅。
      • 好的,我同意你的第一条评论,它的 O(n*m)。另一方面,我喜欢只有一个返回点的口头禅,我总是使用它。对我来说,查看函数内部有多少返回点更复杂。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-06
      相关资源
      最近更新 更多