2009-03-23 3 views
0

Есть ли способ поиска списка для более одного последовательного значения? Я ищу Find и IndexOf, но Find использует Predicates, которые используют только текущее значение, а IndexOf принимает только байтовые параметры.Как искать список (из байта) для двух значений с помощью Framework?

Я могу написать свое собственное решение, но я хочу быть уверенным, что для этой общей проблемы уже нет решения.

Заранее спасибо.

ответ

0

Я не думаю, что это особенно распространенная проблема, если честно - я почти уверен, что в рамках нет ничего.

Я подозреваю, что вам нужно будет решить, хотите ли вы эффективности или простоты реализовать свои собственные. Довольно простое расширение метода версия может выглядеть следующим образом:

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; 
} 
+0

Это просто, поскольку мы можем искать список или массив для одного элемента, как обычно, для поиска более чем один элемент. В любом случае спасибо за ваш ответ, я закодировал общее решение, которое ищет n элементов. – 2009-03-23 10:54:19

1

Одна идея может быть разбить список на группы последовательных значений, а затем сравнить содержимое каждого. Вот еще одна функция (снятая с основной библиотеки 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(); 
0

Это мое собственное решение вопроса. Мне нравится метод, потому что он может обрабатывать любое количество элементов, это 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 
+0

Это не O (n). Это O (n * m), где m - размер значения поиска. Если вам нужно искать XXXXXXXXXXXXXXXXXY в строке, которая представляет собой только XXXXXXXXXXXXXXXXXXXXX и т. Д., То вы сделаете много ненужных сравнений. –

+0

Я бы также рекомендовал вернуться непосредственно из цикла, когда вы нашли совпадение. Мне никогда не нравилась мантра, делающая код сложнее, чтобы убедиться, что есть только одна точка возврата. –

+0

Хорошо, я согласен с вашим первым комментарием, его O (n * m). С другой стороны, мне нравится мантра только одного возвращающегося момента, и я всегда использую ее. Для меня его сложнее посмотреть, сколько точек возврата внутри функции. – 2009-03-23 11:33:11