Быстрый анализ строки в C # - PullRequest
6 голосов
/ 01 июля 2010

Какой самый быстрый способ разбора строк в C #?

В настоящее время я просто использую индексирование строк (string[index]), и код выполняется достаточно разумно, но я не могу не думать, что непрерывная проверка диапазона, выполняемая средством доступа к индексам, должна что-то добавлять.

Итак, мне интересно, какие методы я должен рассмотреть, чтобы дать ему толчок.Это мои первые мысли / вопросы:

  1. Используйте такие методы, как string.IndexOf() и IndexOfAny(), чтобы найти интересующие вас символы.Это быстрее, чем сканирование строки вручную с помощью string[index]?
  2. Использование регулярных выражений.Лично мне не нравятся регулярные выражения, так как мне сложно их поддерживать, но могут ли они выполняться быстрее, чем сканирование строки вручную?
  3. Использовать небезопасный код и указатели.Это исключило бы проверку диапазона индекса, но я читал, что небезопасный код не будет работать в ненадежных средах.Каковы именно последствия этого?Означает ли это, что вся сборка не будет загружаться / запускаться, или только код, помеченный как небезопасный, откажется запускаться?Библиотека может потенциально использоваться во многих средах, поэтому было бы неплохо вернуться к более медленному, но более совместимому режиму.
  4. Что еще я мог бы рассмотреть?

Примечание: я должен сказать, что строки, которые я анализирую, могут быть достаточно большими (скажем, 30 КБ) и в произвольном формате, для которого нет стандартного синтаксического анализатора .NET.Кроме того, производительность этого кода не является сверхкритической, так что это отчасти просто теоретический вопрос любопытства.

Ответы [ 2 ]

2 голосов
/ 01 июля 2010

30k - это не то, что я считаю большим.Прежде чем взволноваться, я бы профиль.Индексатор должен быть в порядке для наилучшего баланса гибкости и безопасности.

Например, чтобы создать строку размером 128 КБ (и отдельный массив такого же размера), заполните ее ненужным (включая время обработки Random) и для суммирования всех кодовых точек символов с помощью индексатора требуется ... 3 мс:

        var watch = Stopwatch.StartNew();
        char[] chars = new char[128 * 1024];
        Random rand = new Random(); // fill with junk
        for (int i = 0; i < chars.Length; i++) chars[i] =
             (char) ((int) 'a' + rand.Next(26));

        int sum = 0;
        string s = new string(chars);
        int len = s.Length;
        for(int i = 0 ; i < len ; i++)
        {
            sum += (int) chars[i];
        }
        watch.Stop();
        Console.WriteLine(sum);
        Console.WriteLine(watch.ElapsedMilliseconds + "ms");
        Console.ReadLine();

Для файлов размером * * * * * * * *следует использовать подход - StreamReader и т. д.

1 голос
/ 01 июля 2010

«Парсинг» - довольно неточный термин. Поскольку вы говорите о 30k, кажется, что вы имеете дело с какой-то структурированной строкой, которую можно покрыть, создав парсер с помощью инструмента генератора парсеров.

Хорошим инструментом для создания, поддержки и понимания всего процесса является система разбора GOLD Девина Кука: http://www.devincook.com/goldparser/

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

Что касается ваших очков:

  1. обычно бесполезен для разбора, который идет дальше, чем разбиение строки.

  2. лучше подходит, если нет рекурсий или слишком сложные правила.

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

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