字符串的 IndexOfAll 函数,带计数参数
IndexOfAll function for string, with count parameter
我想编写一个 IndexOfAll 函数,该函数必须 return 在该字符串中找到的给定模式的所有出现的索引。
该函数有一个 startIndex 和 count 参数,就像内置 .NET 函数的重载之一:string.IndexOf()
count参数,和内置的.NET函数一样,会代表number/max。要在源字符串中检查的字符位置范围。
问题是,我正在努力思考如何正确计算 count 的值。可能这将是一个非常简单的数学计算,但我不明白,我最终得到 count 的负数值(这就是为什么我有一个 try/catch 块下面的代码,因为错误的计数值计算我最终得到一个异常)...
那么,我如何计算 count 值?。这是我的:
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
注意: 调用内置 string.IndexOf()
函数对我来说没问题,至少现在是这样。我不会假装尝试实现复杂的字符串解析算法(可能会被破坏)来执行与 string.IndexOf()
完全相同的操作,但只需几秒或几毫秒,具体取决于字符串的大小。
找到结束索引(startIndex + count
),然后减去新的开始索引。
您还需要在将索引添加到列表之前检查它。
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
可以用 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
Skip and Take 的目的是只查看我们将开始比较的第一个字符。 Select 获取字符及其索引。但是因为我们跳过了,所以我们需要将 startIndex 添加回 IndexOf 中。 Select 然后 returns 字符位置。其中 returns 只有那些非负数的字符位置。
我想编写一个 IndexOfAll 函数,该函数必须 return 在该字符串中找到的给定模式的所有出现的索引。
该函数有一个 startIndex 和 count 参数,就像内置 .NET 函数的重载之一:string.IndexOf()
count参数,和内置的.NET函数一样,会代表number/max。要在源字符串中检查的字符位置范围。
问题是,我正在努力思考如何正确计算 count 的值。可能这将是一个非常简单的数学计算,但我不明白,我最终得到 count 的负数值(这就是为什么我有一个 try/catch 块下面的代码,因为错误的计数值计算我最终得到一个异常)...
那么,我如何计算 count 值?。这是我的:
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
注意: 调用内置 string.IndexOf()
函数对我来说没问题,至少现在是这样。我不会假装尝试实现复杂的字符串解析算法(可能会被破坏)来执行与 string.IndexOf()
完全相同的操作,但只需几秒或几毫秒,具体取决于字符串的大小。
找到结束索引(startIndex + count
),然后减去新的开始索引。
您还需要在将索引添加到列表之前检查它。
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
可以用 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
Skip and Take 的目的是只查看我们将开始比较的第一个字符。 Select 获取字符及其索引。但是因为我们跳过了,所以我们需要将 startIndex 添加回 IndexOf 中。 Select 然后 returns 字符位置。其中 returns 只有那些非负数的字符位置。