最简单的ClosestIndexOf实现

时间:2015-04-01 10:49:00

标签: c# optimization conditional-statements

我想编写一个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,我将不得不引入其他条件。我没有添加这些,因为这正是我试图优化的内容。

您会对初始代码进行哪些优化,以使其更短,性能更好,条件更少?

4 个答案:

答案 0 :(得分:0)

获取所有出现的搜索字符和此事件的found_index。计算search_indexfound_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支票,因为IndexOfLastIndexOf已经这样做了。其他一切都非常易读和易懂。