Home > Mobile >  IndexOfAll function for string, with count parameter
IndexOfAll function for string, with count parameter

Time:02-01

I would like to write a IndexOfAll function that must return the indices of all the occurrences of the given pattern found within that string.

The function has a startIndex and count parameters like one of the overloads of the built-in .NET function: string.IndexOf()

The count parameter, like in the built-in .NET function, it will represent the number / max. range of character positions to examine in the source string.

The problem is that I'm breaking my head trying to figure how to properly calculate the value for count. Probably this would be a very easy mathematical calculation but I don't get it, and I end up with negative numeric values for count (that's why I have a try/catch block in the code below, because due the wrong count value calculation I end getting a exception)...

So, how I calculate the count value?. This is what I have:

Public Function IndexOfAll(str As String,
                           find As String,
                           startIndex As Integer,
                           count As Integer,
                           comparisonType As StringComparison) As Integer()

    Dim indices As New Collection(Of Integer)()
    Dim index As Integer = str.IndexOf(find, startIndex, count, comparisonType)
    indices.Add(index)

    Do
        startIndex = index   1
        count = ???
        ' Console.WriteLine($"idx {index}, start {startIndex}, count {count}")
        Try
            index = str.IndexOf(find, startIndex, count, comparisonType)
            indices.Add(index)
        Catch ex As Exception
            Exit Do
        End Try
    Loop

    Return indices.ToArray()

End Function

NOTE: calling the built-in string.IndexOf() function it's fine for me, at least for now. I don't pretend to try implement complex string parsing algorithms (that maybe could be broken) to do exact the same as string.IndexOf() but with just in few less seconds or milliseconds depending on how large the string is.

CodePudding user response:

Find the end index (startIndex count), and then subtract the new start index.

You'll also want to check the index before adding it to the list.

Public Function IndexOfAll(
    str As String,
    find As String,
    startIndex As Integer,
    count As Integer,
    comparisonType As StringComparison) As Integer()
    
    Dim endIndex As Integer = startIndex   count
    Dim indices As New Collection(Of Integer)()
    Dim index As Integer = str.IndexOf(find, startIndex, count, comparisonType)
    
    Do While index <> -1
        indices.Add(index)
        startIndex = index   1
        count = endIndex - startIndex
        index = str.IndexOf(find, startIndex, count, comparisonType)
    Loop
    
    Return indices.ToArray()
End Function

CodePudding user response:

It can be done with a LINQ one-liner

Public Function IndexOfAll(source As String, find As String, startIndex As Integer, count As Integer, comparisonType As StringComparison) As IEnumerable(Of Integer)
    Return source.
        Skip(startIndex).
        Take(source.Length - find.Length - startIndex   1).
        Select(Function(c, i) source.IndexOf(find, i   startIndex, count, comparisonType)).
        Where(Function(i) i >= 0)
End Function

The purpose of Skip and Take is to look at only those first characters where we will start comparison. The Select takes the character and its index. But since we Skip, we need to add the startIndex back within IndexOf. Select then returns the character position. Where returns only those character positions which are non negative.

  •  Tags:  
  • Related