我想编写一个C#字符串扩展方法ClosestIndexOf(char, index)
,它可以让我获得索引周围字符串中某些字符的最接近索引。
让我用输入字符串检查一些例子:
0 1 2 3 4 5
01234567890123456789012345678901234567890123456789012345
--------------------------------------------------------
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
输入字符串长度为56(我添加了以0开头的索引位置。
示例结果调用:
input.ClosestIndexOf(' ', 30); // 27
input.ClosestIndexOf(' ', 35); // 39
input.ClosestIndexOf(' ', 50); // 50
input.ClosestIndexOf(' ', 19); // 17 & 21 have same offset, return 21
input.ClosestIndexOf(' ', 60); // OutOfRangeException
input.ClosestIndexOf('x', 30); // -1
到目前为止,我已经写过这篇文章了,但是它还需要更多的测试,并且也很丑陋且条件太多。
// index is out of range
if (index > value.Length)
throw new ArgumentOutOfRangeException();
// get closest index below and above specified "index" position
int below = result.LastIndexOf('-', index - 1);
int above = result.IndexOf('-', index);
// followed by conditions
我希望这个问题或多或少是一个数学问题/表达式,这样我就可以避免条件并使其更简单。
This is initial code让你继续工作。从结果中可以看出,当特定字符低于及高于或两者都没有时,我的初始代码才有效。但是,如果每个条件的值都为-1,我将不得不引入其他条件。我没有添加这些,因为这正是我试图优化的内容。
您会对初始代码进行哪些优化,以使其更短,性能更好,条件更少?
答案 0 :(得分:0)
获取所有出现的搜索字符和此事件的found_index
。计算search_index
和found_index
之间的距离。
d = abs(s - f);
以最小距离保持出现。
答案 1 :(得分:0)
可能不是 最好的方法,但这应避免大多数不必要的检查。
public static int ClosestIndexOf(this string input, char c, int index)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
if (index < 0 || index >= input.Length)
{
throw new ArgumentOutOfRangeException("index");
}
var lowerInRange = true;
var higherInRange = true;
for (var i = 0; i < input.Length; i++)
{
if (lowerInRange)
{
var lower = index - i;
lowerInRange = lower >= 0;
if (lowerInRange && input[lower] == c)
{
return lower;
}
}
if (higherInRange)
{
var higher = index + i;
higherInRange = higher < input.Length;
if (higherInRange && input[higher] == c)
{
return higher;
}
}
if (!lowerInRange && !higherInRange)
{
break;
}
}
return -1;
}
答案 2 :(得分:0)
这应该易于理解,高效和安全;是正确的:&#39;)
public static int ClosestIndexOf(this string input, char c, int startIndex)
{
var inputLength = input.Length;
if (inputLength == 0)
return -1;
if (startIndex < 0 || startIndex >= inputLength)
throw new ArgumentOutOfRangeException("startIndex");
int leftIndex = startIndex;
int rightIndex = startIndex;
bool canCheckLeftIndex = true;
bool canCheckRightIndex = true;
do
{
if (canCheckLeftIndex && input[leftIndex] == c) return leftIndex;
if (canCheckRightIndex && input[rightIndex] == c) return rightIndex;
leftIndex--;
rightIndex++;
canCheckLeftIndex = leftIndex >= 0;
canCheckRightIndex = rightIndex < inputLength;
} while (canCheckLeftIndex || canCheckRightIndex);
return -1;
}
您的初始代码:不做任何数学技巧/尝试聪明,我不希望在生产中看到该代码。很难看出你的代码是正确的。
答案 3 :(得分:0)
我已经消除了尽可能多的条件,同时保持整个代码的可维护性和易读性,这也是主要目标之一,因为维护不可读的代码与从头开始编写代码一样糟糕。
public static int ClosestIndexOf(this string input, string value, int startIndex)
{
// get closest index below and above specified "startIndex" position
int above = input.IndexOf(value, startIndex);
int below = input.LastIndexOf(value, startIndex);
int middle = (below + above) / 2;
int result;
if (middle > startIndex)
result = below == -1 ? above : below;
else
result = above == -1 ? below : above;
return result;
}
我已删除了无效的startIndex
支票,因为IndexOf
和LastIndexOf
已经这样做了。其他一切都非常易读和易懂。