2016-09-20 2 views
1

Вот пример строки в вопросе:C# Строка обработка без разделителей строки в список

[952,M] [782,M] [782] {2[373,M]} [1470] [352] [235] [234] {3[610]}{3[380]} [128] [127] 

Я добавил пространство, но это на самом деле не помогает разбивке. Я хочу сделать каждое «поле» в квадратных скобках и добавить его в список строк. Следующий вопрос, который я могу обработать, - это некоторые поля, которые также разделены запятыми, которые я могу разделить после факта. Реальная проблема заключается в фигурных скобках. Например, {2[373,M]} Число вне квадратных скобок представляет собой повторение квадратных скобок.

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

Квази код следующим образом:

for(i = 0 to string.length) 
{ 
    if string.substring(i,1) = "]" 
     int start1 = i 
    elseif string.substring(i,1)="[" 
     int start1 = i 
    elseif string.substring(i,1) = "{" 
     int start2 = i 
    elseif string.substring(i,1) = "}" 
     int end2 = i 
} 

Я думал об использовании идеи коды выше, чтобы подстроки каждое «поля», но фигурные скобки содержат квадратные скобки. Любые идеи очень приветствуются.

+1

нехватка пространства в '{3 [610]} {3 [380]}' опечатка или что-то, что вы можете ожидать в вашем вход? –

+0

1) Что вы хотите * '{2 [373, M]}', чтобы превратиться? Две строки '373, M'? 2) 'string.substring (i, 1) =="] "' смешно. Просто выполните 'string [i] == ']''. – itsme86

+0

Asad Saeeduddin Это ошибка в моей струнной манипуляции. – jhdeval

ответ

1
var s = "[952,M] [782,M] [782] {2[373,M]} [1470] [352] [235] [234] {3[610]}{3[380]} [128] [127]"; 

var s2 = Regex.Replace(s, @"\{(\d+)(\[[^]]+\])\}", m => string.Concat( 
    Enumerable.Repeat(m.Groups[2].Value, int.Parse(m.Groups[1].Value)))); 

var a = s2.Split("[] ".ToArray(), StringSplitOptions.RemoveEmptyEntries); 

// s2 = "[952,M] [782,M] [782] [373,M][373,M] [1470] [352] [235] [234] [610][610][610][380][380][380] [128] [127]" 
// a = {"952,M","782,M","782","373,M","373,M","1470","352","235","234","610","610","610","380","380","380","128","127"} 
0

Вы можете использовать регулярное выражение.

Edited: это управляет проблемы с запятыми и repetititon:

 var regex3 = new Regex(@"(\B\[([a-zA-Z0-9\,]+)\])|(\{(\d+)\[([a-zA-Z0-9\,]+)\]\})"); 
     var stringOne = "[952,M] [782,M] [782] {2[373,M]} [1470] [352] [235] [234] {3[610]}{3[380]} [128] [127]"; 
     var matches = regex.Matches(stringOne); 

     var listStrings = new List<string>(); 

     foreach (Match match in matches) 
     { 
      var repetitor = 1; 
      string value = null; 
      if (match.Groups[1].Value == string.Empty) 
      { 
       repetitor = int.Parse(match.Groups[4].Value); 
       value = match.Groups[5].Value; 
      } 

      else 
      { 
       value = match.Groups[2].Value; 
      } 

      var values = value.Split(','); 
      for (var i = 0; i < repetitor; i++) 
      { 
       listStrings.AddRange(values); 
      } 
     } 
+0

Это мертво близко, единственная проблема с этим - фигурные скобки. Число вне квадратных скобок указывает на повторение. Это {3 [610]} будет добавлено в список 3 раза. – jhdeval

1

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

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

var input = @"[952,M] [782,M] [782] {2[373,M]} 
       [1470] [352] [235] [234] {3[610]}{3[380]} [128] [127]"; 

var pattern = @"((:?\{(\d+)(.*?)\})|(:?\[.*?\]))"; 

MatchCollection matches = Regex.Matches(input, pattern); 

var ls = new List<string>(); 

foreach(Match match in matches) 
{ 
    // check if the item has curly brackets 
    // The captures groups will be different if there were curly brackets 

    // If there are brackets than the 4th capture group 
    // will have the value of the square brackets and it's content 
    if(match.Groups[4].Success) 
    { 
     var value = match.Groups[4].Value; 

     // The "Count" of the items will 
     // be in the third capture group 
     var count = int.Parse(match.Groups[3].Value); 

     for(int i=0;i<count;i++) 
     { 
      ls.Add(value); 
     } 

    } 
    else 
    { 
     // otherwise we know that square bracket input 
     // is in the first capture group 
     ls.Add(match.Groups[1].Value); 
    } 
} 

Вот рабочая скрипку решения: https://dotnetfiddle.net/4rQsDj

Вот результат:

[952,M] 
[782,M] 
[782] 
[373,M] 
[373,M] 
[1470] 
[352] 
[235] 
[234] 
[610] 
[610] 
[610] 
[380] 
[380] 
[380] 
[128] 
[127] 

Если вы не хотите, скобки могут избавиться от них, изменив шаблон регулярного выражения для (:?(:?\{(\d+)\[(.*?)\]\})|(:?\[(.*?)\])) и match.Groups[1].Value - match.Groups[6].Value.

Здесь рабочий раствор без квадратных скобок: https://dotnetfiddle.net/OQwStf

+0

Это похоже на лучшее решение RegEx. Мне было бы интересно узнать о производительности по сравнению с моим решением. –

+0

@JonathanWood не уверен, знаю, что есть определенные проблемы с производительностью Regex в очень больших строках, возможно, я буду возиться со скрипкой, если я заметлю что-нибудь – konkked

+0

На линиях текста 1 тыс. Взято 0,08, а по 500 взято 0,03 секунд, поэтому выглядит как линейный рост, возможно, улучшит производительность, если разработчик скомпилировал его – konkked

1

Регулярное выражение ниже будет обрабатывать обе ситуации:

(?:\{([^\[]+)){0,1}\[([^\]]+)\]\}{0,1} 

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

Regex Demo

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

1

Хотя вы можете быть в состоянии чтобы попасть на RegEx, это может оказаться коротким, если ваши потребности слишком усложняются. Поэтому приведенный ниже код показывает общий подход, который я бы предпринял для достижения этого. Это немного быстро и грязно, но соответствует вашим требованиям.

Кроме того, у меня есть parsing helper class, который сделает этот код более удобным для записи и более надежным.

string input = "[952,M] [782,M] [782] {2[373,M]} [1470] [352] [235] [234] {3[610]}{3[380]} [128] [127]"; 
int pos = 0; 

void Main() 
{ 
    while (pos < input.Length) 
    { 
     SkipWhitespace(); 
     if (pos < input.Length && input[pos] == '{') 
      ParseBrace(); 
     else if (pos < input.Length && input[pos] == '[') 
      ParseBracket(); 
    } 
} 

void SkipWhitespace() 
{ 
    while (pos < input.Length && char.IsWhiteSpace(input[pos])) 
     pos++; 
} 

void ParseBrace() 
{ 
    Debug.Assert(pos < input.Length && input[pos] == '{'); 
    int pos2 = input.IndexOf('[', pos + 1); 
    if (pos2 < 0) 
     pos2 = input.Length; 

    int count = int.Parse(input.Substring(pos + 1, pos2 - pos - 1)); 
    for (int i = 0; i < count; i++) 
    { 
     pos = pos2; 
     ParseBracket(); 
    } 

    pos2 = input.IndexOf('}', pos2 + 1); 
    if (pos2 < 0) 
     pos2 = input.Length; 

    pos = pos2 + 1; 
} 

void ParseBracket() 
{ 
    Debug.Assert(pos < input.Length && input[pos] == '['); 
    int pos2 = input.IndexOf(']', pos + 1); 
    if (pos2 < 0) 
     pos2 = input.Length; 
    Console.WriteLine(input.Substring(pos + 1, pos2 - pos - 1)); 
    pos = pos2 + 1; 
} 

Пример вывода:

952,M 
782,M 
782 
373,M 
373,M 
1470 
352 
235 
234 
610 
610 
610 
380 
380 
380 
128 
127 
Смежные вопросы