Java string.split против C# Regex.split - ограничение до определенного количества полей - PullRequest
0 голосов
/ 06 февраля 2020

Я Java разработчик, но работаю над C# проектом. Что мне нужно сделать, это разделить строку по разделителю, но ограничить ее определенным количеством полей. В Java я могу сделать это:

String message = "xx/xx - xxxxxxxxxxxxxxxxxxx - xxxxxxx";
String[] splitMessage = message.split("\\s-", 3);

В этом случае он разделит его на -, но я также хочу, чтобы он проверял любой пробел перед параметром da sh и ограничить его 3 полями строки. Проходящая строка разбивается на ___ - ____________ - _________, где первый пробел является датой (например, 12/31), второй пробел - сообщение о строке, а третий пробел - местоположение, привязанное к сообщению. Причина, по которой я ограничил его тремя полями, поэтому массив only имеет 3 элемента. Причина, по которой я это делаю, заключается в том, что иногда в сообщении могут быть тире, чтобы оно выглядело так: 12/31 - Test message - test - Test City, 11111. Поэтому мой код Java, приведенный выше, разделил бы его на следующее:

0: 12/31
1: Test message - test
2: Test City, 11111

Я пытаюсь добиться чего-то похожего в C#, но не уверен, как ограничить это определенным количеством полей. Это мой C# код:

var splitMessage = Regex.Split(Message, " -");

Проблема в том, что без ограничения он разбивает его на 4 или 5 полей, а не только на 3. Например, если это было сообщение: 12/31 - My test - don't use - just a test - Test City, 11111, он будет возвращать строку [] с 5 индексами:

0: 12/31
1: My test
2: don't use
3: just a test
4: Test City, 11111

Когда я хочу, чтобы он возвращал это:

0: 12/31
1: My test - don't use - just a test
2: Test City, 11111

Прежде чем вы спросите, я не могу изменить входящая строка Я должен разобрать это так же, как я сделал в Java. Так есть ли эквивалент ограничения до 3 полей? Есть ли лучший способ сделать это, кроме использования Regex.Split()?

Ответы [ 3 ]

2 голосов
/ 06 февраля 2020

Если вы хотите разделить на основе первого и последнего экземпляра -, так что вы получите ровно три поля (при условии, что в строке есть хотя бы две тире), C# действительно имеет аккуратный трюк для этого. C# Regex допускает просмотр за пределами фиксированной ширины. Поэтому следующее регулярное выражение:

(?<=^[^-]*)-|-(?=[^-]*$)

(<=      //start lookbehind
   ^     //look for start of string
   [^-]* //followed by any amount of non-dash characters
)        //end lookbehind
-        //match the dash
|        //OR
-        //match a dash
(?=      //lookahead for
   [^-]* //any amount of non-dash characters
   $     //then the end of the string
)        //end lookahead

Будет соответствовать первому и последнему da sh и позволит вам разбить строку так, как вы хотите.

var splitMessage = Regex.Split(Message, "(?<=^[^-]*)-|-(?=[^-]*$)");

Обратите внимание, что это также не имеет проблем с разбиением на менее трех групп, если тире меньше, но не разбивается более чем на три.

0 голосов
/ 06 февраля 2020

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

Однако вы можете использовать пользовательское регулярное выражение, которое потребляет как можно больше во втором группа для анализа указанного ввода:

var splitMessage = Regex.Match("12/31 - Test message - test - Test City, 11111", "^(.+?) - (.+) - (.+)$")
    .Groups
    .Cast<Group>()
    // skip first group which is the entire match
    .Skip(1)
    .Select(x => x.Value)
    .ToArray();

Учитывая, что первая группа - "xx / xx", вы также можете использовать это регулярное выражение вместо:

"^(../..) - (.+) - (.+)$"
// or, assuming they are date
"^(\d{2}/\d{2}) - (.+) - (.+)$"

РЕДАКТИРОВАТЬ: Или, вы можете просто разделить на «-», а затем объединить все в середине вместе, когда есть более 3 совпадений:

var groups = "12/31 - Test message - test - Test City, 11111".Split(new[] { " - " }, StringSplitOptions.None);
if (groups.Length > 3)
{
    groups = new[]
    {
        groups[0],
        string.Join(" - ", groups.Skip(1).Take(groups.Length - 2)),
        groups[groups.Length - 1]
    };
}
0 голосов
/ 06 февраля 2020

Когда мне нужно разделить строку в определенных разделителях, включая дополнительные пробелы, я обычно делаю это следующим образом:

String message = "xx/xx - xxxxxxxxxxxxxxxxxxx - xxxxxxx";
String[] splitMessage = message.split(" *- *", 3);    
System.out.println(Arrays.asList(splitMessage));

Выходы: [xx / xx, xxxxxxxxxxxxxxxxxxx, xxxxxxx]

String message = "12/31 - My test - don't use - just a test - Test City; 11111";
String[] splitMessage = message.split(" *- *", 3);    
System.out.println(Arrays.asList(splitMessage));

Выходы: [12/31, Мой тест, не используйте - просто тест - Тест Сити; 11111]

Но вам, кажется, нужно что-то другое:

splitMessage[0] shall contain the first part
splitMessage[1] shall contain the second and third part
splitMessage[2] shall contain the rest

Как вы хотите сообщить компьютеру, что второй элемент вывода должен состоять из двух частей? Я думаю, что это невозможно, кроме как разбить строку на все 5 частей, а затем заново объединить части вместе, как вы хотите.

Возможно, не ясно, какой результат вы хотите. Можете ли вы уточнить требование более четко: что произойдет, если входная строка содержит более 3 элементов?

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