Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/37: Рейтинг темы: голосов - 37, средняя оценка - 4.73
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
.NET 4.x

Быстрейший способ отделить число от букв

13.09.2024, 13:11. Показов 9023. Ответов 117
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.
Есть строки такого вида:
Code
1
2
3
4
1.5224V
1.5225mV
1.526 mV
1.527 V
Соответственно, число - это значение (всегда double!), а буквы - ед. измерения.
Необходимо наиболее быстро распарсить их.

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

Сначала первый вариант (без пробела) я парсил так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (RegexPattern.IsFiltered(message))
{
    const string numbers = "0123456789.";
    var numberBuilder = new StringBuilder();
    var unitBuilder = new StringBuilder();
 
    foreach (char c in message)
    {
        if (numbers.IndexOf(c) > -1)
            numberBuilder.Append(c);
        else
            unitBuilder.Append(c);
    }
 
    double.TryParse(numberBuilder.ToString(), out double value);
    rawVoltage = value;
    Mv = unitBuilder.ToString() == "mV";
}
а второй просто Regex'ом: @"^\d+\.\d+\s{1}m?V$"

Затем сделал "общий" Regex для обоих этих случаев: @"^\d+\.\d+\s?m?V$"
и теперь их значения достаю вот так:
C#
1
2
3
4
5
6
if (IsVoltage(s))
{
    Console.Write($"Voltage: {RegexVoltageValue().Match(s).Value}\t");
    Console.Write($"Unit: {RegexUnitValue().Match(s).Value}");
    Console.WriteLine();
}
где сами регулярки такие:
C#
1
2
3
4
5
[GeneratedRegex(@"\d+\.\d+")]
private static partial Regex RegexVoltageValue();
 
[GeneratedRegex(@"(m?V)$")]
private static partial Regex RegexUnitValue();
По скорости работы StringBuilder VS Regex, вроде бы, немного выигрывает Regex, однако где-то я читал, что они медленнее, чем выборка нужного из цикла..
На простом коде сложно определить, т.к. разница незначительна, но вдруг случится "что-то", что намного затормозит этот процесс с Regex'ом?
Т.е. не поменял ли я шило на мыло?
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.09.2024, 13:11
Ответы с готовыми решениями:

Отделить цифры от букв и найти сумму цифр
Есть массив,N размера.В массиве присутствуют буквы и цифры.Нужно отделить цифры от букв и найти сумму цифр: отделяем буквы от цифр: ...

Автомобильные номера состоят из 1,2, или 3 букв и 4 цифр. используется 30 букв, найти число таких букв
Автомобильные номера состоят из 1,2, или 3 букв и 4 цифр. используется 30 букв, найти число таких букв. помогите решить, или объясните...

отделить крупное число от мелкого
например ввожу 4530 результат 4500 и 30 3456 3400 и 56 и т. д.

117
151 / 135 / 29
Регистрация: 02.07.2013
Сообщений: 969
13.09.2024, 13:23
C#
1
2
3
const string numbers = "0123456789.";
if (numbers.IndexOf(c) > -1)
            numberBuilder.Append(c);
не будет ли быстрее через hashset?

если даблы будут в специфичном формате, то может будет быстрее работать если сделать свой посимвольный разбор на си, конвертировав ее в ascci?
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 13:30  [ТС]
Цитата Сообщение от golosalex Посмотреть сообщение
через hashset?
Мне кажется с Hashset будет не быстрее, чем со StringBuilder.. Но может и нет, не изучал этот вопрос.
Тут скорее вопрос в том - на сколько выгоднее (или нет) применить Regex..

Добавлено через 1 минуту
Цитата Сообщение от golosalex Посмотреть сообщение
если даблы будут в специфичном формате
не, даблы всегда именно в таком формате, как в примере строк выше.
0
151 / 135 / 29
Регистрация: 02.07.2013
Сообщений: 969
13.09.2024, 13:41
Цитата Сообщение от wizard41 Посмотреть сообщение
Мне кажется с Hashset будет не быстрее, чем со StringBuilder.. Но может и нет, не изучал этот вопрос.
Тут скорее вопрос в том - на сколько выгоднее (или нет) применить Regex..
я имел виду оставить логику со стрингбилдером и заменить поиск символа в константной строке на проверку наличия символа в хешсете. или может проверку c<9 && c>0 || c == '.' в общем избавится от indexof

Цитата Сообщение от wizard41 Посмотреть сообщение
не, даблы всегда именно в таком формате, как в примере строк выше.
тогда ручной парсинг asci строки на си будет сделать несложно. но не уверен что поможет, вдруг double.Parse какой-то низкоуровневый аппаратный хак использует.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 13:50  [ТС]
Цитата Сообщение от golosalex Посмотреть сообщение
в общем избавится от indexof
Да. но цикл то останется...
На самом деле, при реальной работе этого кода проблем пока не возникало (выборка и обработка происходит каждые 70-100 мс), но мне кажется, таким образом система через чур "напрягается", когда можно это сделать более проще и быстрее..
Ну и вдруг, время между обработками сократиться, то не возникнет ли эффекта пропусков..

Добавлено через 4 минуты
P.S.
тем более что, все равно соответствие строк данному формату определяется именно Regex'ом. Поэтому, тут можно прямо из самой проверки сразу выдергивать эти значения с помощью Group[x]... (наверное)
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9673 / 4825 / 763
Регистрация: 17.04.2012
Сообщений: 9,664
Записей в блоге: 14
13.09.2024, 13:55
Цитата Сообщение от wizard41 Посмотреть сообщение
выборка и обработка происходит каждые 70-100 мс
Я крайне сомневаюсь, что обработка строк такого размера регексом такой сложности (никакой) будет занимать хотя бы 10 мс, не то что 70.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 14:13  [ТС]
tezaurismosis, согласен, но это не единственная операция, которая выполняется за время "окна", поэтому обработка должна быть насколько возможно короче.

Добавлено через 7 минут
Чуть изменил код - результаты стали: 21мс (цикл с StringBuilder) против 3мс через Regex!
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
string[] msg =
{
    "1.5224V", "1.5225mV", "1.526 mV", "1.527 V"
};
 
 
Stopwatch sw = Stopwatch.StartNew();
foreach (string s in msg)
{
    if (IsVoltage(s))
    {
        Console.Write($"{RegexVoltageValue().Match(s).Value}\t");
        Console.Write(RegexUnitValue().Match(s).Value);
        Console.WriteLine();
    }
}
 
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
 
 
sw.Restart();
foreach (string s in msg)
{
    if (IsVoltage(s))
    {
        stringBuilder(s);
    }
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Добавлено через 38 секунд
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void stringBuilder(string s)
{
    const string numbers = "0123456789.";
    var numberBuilder = new StringBuilder();
    var unitBuilder = new StringBuilder();
 
    foreach (char c in s)
    {
        if (numbers.IndexOf(c) > -1)
            numberBuilder.Append(c);
        else
            unitBuilder.Append(c);
    }
 
    Console.Write(double.Parse(numberBuilder.ToString()) + "\t");
    Console.Write(unitBuilder.ToString());
    Console.WriteLine();
}
Добавлено через 5 минут
Ой, вернее наоборот!

Добавлено через 1 минуту
Regex намного медленнее получился, чем цикл со StringBuilder().
0
2393 / 1922 / 763
Регистрация: 27.07.2012
Сообщений: 5,565
13.09.2024, 14:44
Цитата Сообщение от wizard41 Посмотреть сообщение
Regex намного медленнее получился
Регулярки же можно компилировать, если образец не меняется. Тогда, по идее, побыстрее должны работать.
0
151 / 135 / 29
Регистрация: 02.07.2013
Сообщений: 969
13.09.2024, 15:00
Цитата Сообщение от wizard41 Посмотреть сообщение
Чуть изменил код - результаты стали: 21мс (цикл с StringBuilder) против 3мс через Regex!
а бенчмарк проходит через стопвотч? тогда хотя бы надо длинный пример ему скормить и в цикле гонять чтобы статистику набрать
0
Администратор
Эксперт .NET
 Аватар для tezaurismosis
9673 / 4825 / 763
Регистрация: 17.04.2012
Сообщений: 9,664
Записей в блоге: 14
13.09.2024, 15:57
Цитата Сообщение от wizard41 Посмотреть сообщение
Чуть изменил код - результаты стали: 21мс (цикл с StringBuilder) против 3мс через Regex!
Это Debug сборка?
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 16:26  [ТС]
Цитата Сообщение от John Prick Посмотреть сообщение
Регулярки же можно компилировать
Это я знаю, все равно они в среднем в 5 раз длительнее..
Цитата Сообщение от golosalex Посмотреть сообщение
тогда хотя бы надо длинный пример ему скормить и в цикле гонять чтобы статистику набрать
Ага.
Цитата Сообщение от tezaurismosis Посмотреть сообщение
Это Debug сборка?
Да. А в релизе будет наоборот?

Добавлено через 10 минут
golosalex, кстати, по поводу HashSet - он для отсеивания дублей хорош, а в данном случае его примение под вопросом. Например, на строке 1.99 V он вторую девятку "забракует" и она не войдет в результат.
По поводу статистики на больших входных коллекциях - ну тоже не особый вариант, ведь здесь важна именно единичная обработка, т.к. входные данные приходят не кучей, а по отдельности. Т.е. важно время обработки одной строчки.
0
fly
 Аватар для I can
4946 / 4629 / 843
Регистрация: 13.04.2015
Сообщений: 9,810
13.09.2024, 17:01
Лучший ответ Сообщение было отмечено wizard41 как решение

Решение

Цитата Сообщение от wizard41 Посмотреть сообщение
1.5224V
1.5225mV
1.526 mV
1.527 V
Не знаю, насколько быстро, но все эти значения прекрасно переварит функция Val из Visual Basic
Миниатюры
Быстрейший способ отделить число от букв  
1
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 17:28  [ТС]
Цитата Сообщение от I can Посмотреть сообщение
Не знаю, насколько быстро,
рекордсмен, среди всех вариантов: 1 мс.

Добавлено через 2 минуты
Хотя, само измерение сделано неправильно для всех случаев.

Добавлено через 9 минут
С предварительным "прогревом" метод из VisualBasic самый быстрый, стремится к 0 мс.
Остальные два ~2мс.
0
3259 / 3277 / 556
Регистрация: 17.02.2019
Сообщений: 5,185
13.09.2024, 17:29
Цитата Сообщение от wizard41 Посмотреть сообщение
даблы всегда именно в таком формате, как в примере строк выше.
Так больше 4 цифр после точки не будет. Если так то моно, наверно и взять из строки 6 первых и удалить пробелы если есть.
Или там целая часть может и 2-х значная быть?
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 17:38  [ТС]
Цитата Сообщение от January29 Посмотреть сообщение
удалить пробелы
Зачем? лишняя операция. Он и так удалится при преобразовании.
Цитата Сообщение от January29 Посмотреть сообщение
Или там целая часть может и 2-х значная быть?
Да, и 2-х, и 3-х значная.

Добавлено через 3 минуты
В общем, надо делать нормальный бенч, т.к. при перестановке Regex и StringBuilder методов - первый становится быстрее..
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 17:59  [ТС]
Вариант VisualBasic Conversion.Val(s) однозначно работает быстрее варианта double.Parse(), даже с вычленением единиц измерения через Regex:
C#
1
2
3
4
    if (IsVoltage(s))
    {
        Console.WriteLine($"{Conversion.Val(s)} {UnitValue().Match(s).Value}");
    }
0
112 / 110 / 30
Регистрация: 08.05.2021
Сообщений: 485
13.09.2024, 18:46
запускать бэнч на паре значений(да ещё и с io) это прям сильно. ещё и мерить это всё в "секундах". ещё и значения получать в районе погрешности. + дебаг сборка - в общем, полный комплект.

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

нужен перф(хотя бы уровня шарпа) - юзай либо регеспы, либо какие-то функции из стдлибы. 95% это будет быстрее кода на скриптухе.

Добавлено через 1 минуту
либо на сишке писать как выше кто-то сказал. правда толку от этого - входной формат слишком мусор. но авось, если уж совсем припрёт.
0
 Аватар для MallSerg
91 / 58 / 14
Регистрация: 16.11.2018
Сообщений: 274
13.09.2024, 19:03
Есть подозрение что в ассемблере там тока мов и рет ...
т.е. для константных значений компилятор размотал цикл и вычислил все на этапе компиляции.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3422 / 2741 / 575
Регистрация: 04.09.2018
Сообщений: 8,610
Записей в блоге: 3
13.09.2024, 19:09  [ТС]
Цитата Сообщение от mashmed135 Посмотреть сообщение
бэнчи в несколько проходов на паре гигов данных хотя бы
это я в курсе, но совсем не относится к теме. Миллион данных никогда не поступает, поэтому единственный критерий - время обработки одной строки.
Цитата Сообщение от mashmed135 Посмотреть сообщение
это будет быстрее кода на скриптухе
на какой "скриптухе"? Скрипты мы тут не пишем..
Цитата Сообщение от mashmed135 Посмотреть сообщение
либо на сишке писать как выше кто-то сказал
Вопрос был про быстроту тех или иных имеющихся подходов на C#. С (Си) тут вообще не при делах.

Добавлено через 1 минуту
Цитата Сообщение от MallSerg Посмотреть сообщение
и вычислил все на этапе компиляции.
Наверное нет, т.к. первый "прогревочный" цикл выполняется заметно дольше всех. Иначе они были бы примерно одинаковы..
0
112 / 110 / 30
Регистрация: 08.05.2021
Сообщений: 485
13.09.2024, 19:16
Цитата Сообщение от wizard41 Посмотреть сообщение
это я в курсе, но совсем не относится к теме. Миллион данных никогда не поступает, поэтому единственный критерий - время обработки одной строки.
это неважно. ты ничего на паре строк не замериешь в принципе. вон как выше по теме:
Цитата Сообщение от wizard41 Посмотреть сообщение
при перестановке Regex и StringBuilder методов - первый становится быстрее..
и прочее подобное. если проще - смысл не в том, сколько поступает, а в том, на скольки ты адекватные измерения провести можешь.
Цитата Сообщение от wizard41 Посмотреть сообщение
на какой "скриптухе"? Скрипты мы тут не пишем..
на шарпе.
Цитата Сообщение от wizard41 Посмотреть сообщение
Вопрос был про быстроту тех или иных имеющихся подходов на C#. С (Си) тут вообще не при делах.
ну про подходы в шарпе я выше написал, точнее предположил - авось увидим что-то отличное от этого. а по поводу сишки: насколько я понял, тебе предлагали не всё переписывать, а пару функций написать и дёргать их уже из шарпа. вполне себе подход.

Добавлено через 1 минуту
если бэнч адекватный надумаешь писать - запости сюда потом код и результаты. интересно как шарп себя здесь поведёт.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.09.2024, 19:16
Помогаю со студенческими работами здесь

Строка: Есть ли способ одной строкой менять несколько букв?
var a, b : string; begin a := 'ПРИВЕТ'; b := StringReplace(a, 'П', 'В', ); b := StringReplace(a, 'Р', 'О', ); b :=...

Как преобразовать строку, удалив в ней группы цифр, а группы букв отделить пробелами. Упорядочить полученную последовательность слов
Дана текстовая строка, состоящая из букв и цифр. Преобразовать строку, удалив в ней группы цифр, а группы букв отделить пробелами....

Сумма кодов первой и последней букв: способ разрешения коллизий Бинарное дерево
Привет. Помогите, пожалуйста, с написанием программы: Тип хеш-функции (таблицы)-Сумма кодов первой и последней букв Способ разрешения...

Подсчитать число гласных и согласных букв в множестве и определить, каких букв больше
Подсчитать число гласных и согласных букв в множестве и определить, каких букв больше. Учесть, что в строке могут быть другие символы,...

Перед каждой группой одинаковых букв, вставить число, соответствующее количеству букв
Помогите пожалуйста, очень прощу! В слове, состоящим из цифр и букв и заканчивающимся точкой, перед каждой группой одинаковых букв,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru