Оптимизация метода замены строк - PullRequest
4 голосов
/ 26 февраля 2010

Может кто-нибудь помочь мне, как оптимизировать этот метод?

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    VirtualPathData path = base.GetVirtualPath(requestContext, values);

    if (path != null)
    {
        string virtualPath = path.VirtualPath;
        string condition = string.Empty;

        if (virtualPath.Contains("?"))
        {
            condition = virtualPath.Substring(virtualPath.IndexOf("?"));
            virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?"));
        }

        virtualPath = virtualPath.Replace(@"%C5%BD", "ž");
        virtualPath = virtualPath.Replace(@"%C4%90", "đ");
        virtualPath = virtualPath.Replace(@"%C4%86", "ć");
        virtualPath = virtualPath.Replace(@"%C4%8C", "č");
        virtualPath = virtualPath.Replace(@"%C5%A0", "š");

        virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-");
        virtualPath = virtualPath.Replace(@"-amp;", "&");

        while (virtualPath.Contains("--"))
        {
            virtualPath = virtualPath.Replace("--", "-");
        }

        path.VirtualPath = virtualPath + condition;
    }

    return path;
}

Ответы [ 2 ]

4 голосов
/ 26 февраля 2010

В этом коде вы сканируете строку три раза для символа:

if (virtualPath.Contains("?"))
{
   condition = virtualPath.Substring(virtualPath.IndexOf("?"));
   virtualPath = virtualPath.Substring(0, virtualPath.IndexOf("?"));
}

Вместо этого отсканируйте его один раз и используйте результат три раза. Также просмотрите на символ вместо строки:

int pos = virtualPath.IndexOf('?');
if (pos != -1) {
   condition = virtualPath.Substring(pos);
   virtualPath = virtualPath.Substring(0, pos);
}

Здесь вы делаете несколько замен одной и той же заменой:

virtualPath = virtualPath.ToLower().Replace(",", "-").Replace("%20", "-").Replace("&", "-");

Вместо этого вы можете использовать регулярное выражение для сопоставления их всех:

virtualPath = Regex.Replace(virtualPath.ToLower(), "(,|%20|&)", "-");

(То, дает ли это на самом деле лучшую производительность, необходимо проверить с некоторыми вашими фактическими данными. Несмотря на то, что это меньше операций, есть некоторые издержки при настройке регулярного выражения.)


Вы используете цикл для сокращения кластеров символов:

while (virtualPath.Contains("--"))
{
   virtualPath = virtualPath.Replace("--", "-");
}

Вместо этого вы можете использовать регулярное выражение для единственной замены:

virtualPath = Regex.Replace(virtualPath, "-{2,}", "-");
0 голосов
/ 26 февраля 2010

Ваш самый очевидный первый шаг - использование StringBuilder вместо String.

String является неизменяемым типом. Это означает, что после создания его значение никогда не меняется. Таким образом, для каждого вызова Replace, который вы делаете в своем методе, программа создаст совершенно новый экземпляр String для хранения результата, который требует большого объема памяти и процессора. (Я говорю это сравнительно - вы не собираетесь максимально использовать свою машину, вызывая этот метод один раз, но если вы будете вызывать его тысячи раз, вы обязательно заметите!)

StringBuilder, с другой стороны, является классом, предназначенным для манипулирования строками в памяти, и ему не нужно копировать / воссоздавать память каждый раз, когда вы меняете строку.

Итак, одним большим шагом в правильном направлении было бы использовать это в начале вашего метода:

            StringBuilder sb = new StringBuilder(path.VirtualPath.ToLower());
            string condition = string.Empty;

            int index = path.VirtualPath.IndexOf("?");

            if (index > -1)
            {
                condition = virtualPath.Substring(pos);
                sb.Remove(0, index);
            }

            sb.Replace(@"%C5%BD", "ž")
                .Replace(@"%C4%90", "đ")
                .Replace(@"%C4%86", "ć")
                .Replace(@"%C4%8C", "č")
                .Replace(@"%C5%A0", "š")
                .Replace(",", "-")
                .Replace("%20", "-")
                .Replace("&", "-")
                .Replace(@"-amp;", "&");
             sb.Append(condition);

Обратите внимание, что я также сделал .ToLower () ранее, потому что StringBuilder не имеет эквивалента, а также обратите внимание на sb.Append, который снова предотвратит много переписывания.

Это не так оптимально, как могло бы быть, но это должно быть довольно улучшением ...

Единственное, что я пропустил, это заменить "-". StringBuilder не имеет функции «Содержит», но вы можете использовать регулярное выражение, чтобы перехватить все за один проход (вместо необходимости в цикле).

Надеюсь, что вы начали!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...