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

293
10 ноября 2017, 06:45

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

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

Answer 1

Вместо просмотра вперед, нужно использовать просмотр назад. Для строки вида

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

Answer 2

В данном случае необязательно использовать регулярное выражение: разбейте на массив значений с ;, пропустите 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<Match>()
        .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} раз ({{ в интерполированном строковом литерале задаёт {, а }}}).
Answer 3

Нужно использовать положительный просмотр вперед. Больше деталь про регулярные выражения вы найдете здесь

Ответ на ваш вопрос выглядит так: ((?<=^\d;)\d)

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

Answer 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
Answer 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

READ ALSO
Visual Studio режим &ldquo;только для чтения&rdquo;

Visual Studio режим “только для чтения”

Почему скрипт стает "только для чтения" в Visual Studio C# после нажатия "Подключить к Unity"Как я могу его потом редактировать?

199
Таймаут в GetRequestStream() при получении потока из WebRequest

Таймаут в GetRequestStream() при получении потока из WebRequest

Есть простой код отправляющий сообщения через Web APIВ цикле формируется веб-запрос и отправляется

185
Открытие второго окна в паттерне MVVM

Открытие второго окна в паттерне MVVM

Как ПРАВИЛЬНО реализовать открытие второго окна из кнопки на первом окне с использованием паттерна MVVM? На сети конкретного примера я не нашел,...

196
Передача переменных в паттерне MVVM

Передача переменных в паттерне MVVM

Не могу разобраться со связью VM<>MТочнее как грамотно передавать переменные

205