Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Как получить второе число из строки чисел с разделителем?

#c_sharp #регулярные_выражения


Есть строка чисел разделенных точкой с запятой:

2;1;1;1;1;1;5;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;1;3;17


Не получается получить второе число с начала, в данном случае это 1.

Перепробовал различные варианты, вот один из последних:

(?=(^(\d;){1}))\d
    


Ответы

Ответ 1



В данном случае необязательно использовать регулярное выражение: разбейте на массив значений с ;, пропустите 1-е и возьмите 2-е: var s = "2;1;1;1;1;1;5;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;1;3;17"; var result = s.Split(';').Skip(1).Take(1).FirstOrDefault(); Console.Write(result); // => 1 // или var chunks = s.Split(';'); if (chunks.GetLength(0) > 1) Console.WriteLine(chunks[1]); См. онлайн-демо С помощью регулярного выражения можно найти все последовательности цифр в строке, а потом получить доступ к необходимому значению также как и в первом случае: var chisla = Regex.Matches(s, @"\d+") .Cast() .Select(m => m.Value) .ToList(); var my_value = chisla[1]; // => 1 Можно использовать и более навороченные констркции: var idx = 2; // Получить второе число в строке var m = Regex.Match(s, $@"^(?:;?(\d+)){{{idx}}}"); if (m.Success) { Console.Write(m.Groups[1].Value); // => 1 } Демо регулярного выражения ^ - начало строки (?: - начало незахватываемой группы ;? - 1 или 0 символов ; (\d+) - 1+ цифр ) - конец незахватываемой группы {{{idx}}} - найти шаблоны незахватываемой группы {idx} раз ({{ в интерполированном строковом литерале задаёт {, а }} — }).

Ответ 2



Вместо просмотра вперед, нужно использовать просмотр назад. Для строки вида 2;1;1;1;1;1;5;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;1;3;17 вполне хватит такой регулярки: /(?<=;)\d+/ Тест https://regex101.com/r/mRfIVr/1

Ответ 3



Нужно использовать положительный просмотр вперед. Больше деталь про регулярные выражения вы найдете здесь Ответ на ваш вопрос выглядит так: ((?<=^\d;)\d) (?<=^\d;) - эта часть говорит о том, что перед искомым выражением должна быть одна цифра, точка с запятой и это должны быть первые два символа

Ответ 4



Регулярное выражение: ^(?:\d+;){1}(\d+)/ Мы пропускаем некоторое количество чисел с разделителем и захватываем следующее число. Демо: let data = [1, 12, 13, 14, 15]; let str = data.join(';'); console.log(str); for (let i = 0; i < data.length; ++i) { let reg = new RegExp(`^(?:\\d+;){${i}}(\\d+)`); console.log(str.match(reg)[1]); } C#: int index = 2; string pattern = @"^(?:\d+;){" + index + @"}(\d+)"; string input = "1;23;45;67;89"; Console.WriteLine(Regex.Match(input, pattern).Groups[1].Value); // 45 C# (ручной поиск): string result = ""; // Посимвольный проход по строке for (int charI = 0, numI = 0, N = source.Length; charI < N; ++charI) { char current = source[charI]; // Текущий символ if (current == separator) { // Разделитель ++numI; if (numI > index) break; // Дальше - не интересно } else if (numI == index) { // Все символы нужного токена попадают в результат(не только цифры) result += current; } } Console.WriteLine(result);

Ответ 5



Попробовал позамерять. public class Program { private static string getNthNumber(string s, int n, char separator = ';') { string s_res = ""; for (int charI = 0, numI = 0, N = s.Length; charI < N; ++charI) { char current = s[charI]; if (current == separator) { ++numI; if (s_res == "") continue; break; } else if (numI == n) { s_res += current; } } return s_res; } public static void Main(string[] args) { string src = String.Join(";", Enumerable.Range(0, 10000)); double TEST_SIZE = 15e3; int getIndex = 1100; string sum = ""; int start = Environment.TickCount; for (int i = 0; i < TEST_SIZE; ++i) sum = Program.getNthNumber(src, getIndex); // 5000 double duration = Environment.TickCount - start; double bandwidth = TEST_SIZE/(duration/1000); Console.WriteLine("Manual Bandwidth is " + bandwidth + "test/s"); start = Environment.TickCount; for (int i = 0; i < TEST_SIZE; ++i) sum = src.Split(';').Skip(getIndex).FirstOrDefault(); duration = Environment.TickCount - start; bandwidth = TEST_SIZE/(duration/1000); Console.WriteLine("Split/Skip Bandwidth is " + bandwidth + "test/s"); start = Environment.TickCount; for (int i = 0; i < TEST_SIZE; ++i) sum = Regex.Match(src, @"^(?:\d+;){" + getIndex + @"}(\d+)").Groups[1].Value; duration = Environment.TickCount - start; bandwidth = TEST_SIZE/(duration/1000); Console.WriteLine("Regexp Bandwidth is " + bandwidth + "test/s"); } } Запуск в первом попавшемся онлайн сервисе: Manual Bandwidth is 64516,1290322581test/s Split/Skip Bandwidth is 1523,22924600152test/s Regexp Bandwidth is 3656,3071297989test/s

Комментариев нет:

Отправить комментарий