2009-03-23 3 views
0

Existe-t-il un moyen de rechercher une liste pour plusieurs valeurs consécutives? J'ai regardé Find et IndexOf mais Find utilise des prédicats qui utilisent seulement la valeur courante et IndexOf ne prend que des paramètres d'octets.Comment rechercher une liste (Of Byte) pour deux valeurs en utilisant le Framework?

Je peux coder ma propre solution, mais je veux être sûr qu'il n'y a pas de solution déjà disponible pour ce problème commun.

Merci d'avance.

Répondre

0

Je ne pense pas que ce soit un problème particulièrement commun, pour être honnête - je suis assez sûr qu'il n'y a rien dans le cadre.

Je soupçonne que vous aurez besoin de travailler si vous voulez l'efficacité ou la simplicité pour mettre en œuvre votre propre. Une version de méthode d'extension assez simple pourrait ressembler à ceci:

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

C'est juste que comme nous pouvons rechercher une liste ou un tableau pour un élément ressemble à commun pour rechercher plus qu'un seul article. De toute façon merci pour votre réponse, j'ai codé une solution générique qui recherche n éléments. –

1

Une idée pourrait être de diviser votre liste en groupes de valeurs consécutives, puis comparer le contenu de chacun. Voici une autre fonction (levée de la bibliothèque de base F #) qui effectuera la scission.

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

Vous pouvez utiliser la fonction ci-dessus comme ceci:

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

Ceci est ma propre solution à la question. J'aime la méthode parce qu'elle peut manipuler n'importe quelle quantité d'éléments, est O (n) et son assez simple:

<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

Ce n'est pas O (n). C'est O (n * m) où m est la taille de la valeur de recherche. Si vous devez rechercher XXXXXXXXXXXXXXXXXY dans une chaîne qui est juste XXXXXXXXXXXXXXXXXXXXX etc, alors vous ferez beaucoup de comparaisons inutiles. –

+0

Je vous recommande également de revenir directement de la boucle lorsque vous avez trouvé une correspondance. Je n'ai jamais aimé le mantra de rendre le code plus compliqué juste pour s'assurer qu'il n'y a qu'un seul point de retour. –

+0

Ok, je suis d'accord avec ton premier commentaire, son O (n * m). De l'autre côté j'aime le mantra d'un seul point de retour et je l'utilise toujours. Pour moi, c'est plus compliqué de regarder combien de points de retour il y a dans une fonction. –

Questions connexes