Разделение строки, содержащей несколько символов, для получения определенных значений - PullRequest
0 голосов
/ 20 марта 2012

Не могу поверить, что у меня возникли проблемы с этой следующей строкой

String filter = "name=Default;pattern=%%;start=Last;end=Now";

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

string Name = "Default";
string Pattern = "%%" ;
string start = "Last" ;
string end = "Now" ;

Причина, по которой я спрашиваю, заключается в том, что мой крайний срок очень скоро, и это буквально последнее, что я должен сделать.Я в панике и застрял на этой основной команде.Я попытался:

pattern = filter.Split(new string[] { "pattern=", ";" },
                       StringSplitOptions.RemoveEmptyEntries)[1]; //Gets the pattern
startDate = filter.Split(new string[] { "start=", ";" },
                         StringSplitOptions.RemoveEmptyEntries)[1]; //Gets the start date

Я получаю нужный мне шаблон, но как только я пытаюсь разбить старт, я получаю значение как "Pattern = %%"

Чтоможно ли сделать?

Забыл упомянуть Список в этой строке, который необходимо разбить, может быть не в каком-то конкретном порядке.это единственный образец строки, который будет считан из коллекции stringCollection (чтение этих фильтров из Properties.Settings.Filters

Ответы [ 9 ]

3 голосов
/ 20 марта 2012

Использование string.Split это двухэтапный процесс.

В первом случае разделить на ;, чтобы получить массив пар ключевых слов и значений:

string[] values = filter.Split(';');

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

foreach (string value in values)
{
    string[] pair = value.Split('=');
    string key = pair[0];
    string val = pair[1];
}
2 голосов
/ 20 марта 2012

Это должно сработать:

string filter = "name=Default;pattern=%%;start=Last;end=Now";

// Make a dictionary.
var lookup = filter
   .Split(';')
   .Select(keyValuePair => keyValuePair.Split('='))
   .ToDictionary(parts => parts[0], parts => parts[1]);

// Get values out of the dictionary.
string name = lookup["name"];
string pattern = lookup["pattern"];
string start = lookup["start"];
string end = lookup["end"];
2 голосов
/ 20 марта 2012
String filter = "name=Default;pattern=%%;start=Last;end=Now";
string[] temp = filter.Split('=');
string name = temp[1].Split(';')[0];
string pattern = temp[2].Split(';')[0];
string start = temp[3].Split(';')[0];
string end = temp[4].Split(';')[0];
1 голос
/ 20 марта 2012

Ну, я попробовал что-то вроде этого:

 var result = "name=Default;pattern=%%;start=Last;end=Now".Split(new char[]{'=',';'});

  for(int i=0;i<result.Length; i++)
  {          
      if(i%2 == 0) continue;
      Console.WriteLine(result[i]);
  }

и вывод:

Default
%%
Last
Now

Это то, что вы хотите?

1 голос
/ 20 марта 2012

Видите ли, теперь дело в том, что ваш Split на filter во второй раз все еще начинается с начала строки и совпадает с ;, так как строка имеет не изменились, вы по-прежнему извлекаете предыдущие совпадения (поэтому ваш индексатор отключен на X ).

Вы можете разбить это на проблемные части, например:

var keyValues = filter.Split(';');
var name = keyValues[0].Split('=')[1];
var pattern = keyValues[1].Split('=')[1];
var start = keyValues[2].Split('=')[1];
var end = keyValues[3].Split('=')[1];

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

1 голос
/ 20 марта 2012

Дата начала заканчивается в третьей позиции в массиве:

startDate = filter.Split(new string[] { "start=", ";" }, StringSplitOptions.RemoveEmptyEntries)[2];

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

string[] pairs = filter.Split(';');
string[] values = pairs.Select(pair => pair.Split('=')[1]).ToArray();

string name = values[0];
string pattern = values[1];
string start = values[2];
string end = values[3];

(Этот код, конечно, предполагает, что пары ключ-значение всегда располагаются в одном и том же порядке.)

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

string[] values = filter.Split(new string[] { "=", ";" }, StringSplitOptions.None);

string name = values[1];
string pattern = values[3];
string start = values[5];
string end = values[7];

Редактировать:

Чтобы обработать значения ключа в любом порядке, выполните поиск по строке и выберите из нее значения:

ILookup<string, string> values =
  filter.Split(';')
  .Select(s => s.Split('='))
  .ToLookup(p => p[0], p => p[1]);

string name = values["name"].Single();
string pattern = values["pattern"].Single();
string start = values["start"].Single();
string end = values["end"].Single();

Вы можете использовать SingleOrDefault, если хотите поддерживать отсутствие значений в строке:

string name = values["name"].SingleOrDefault() ?? "DefaultName";

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

foreach (var string name in values["name"]) {
  // do something with the name
}
0 голосов
/ 20 марта 2012

Я тоже нашел простое решение. Большинство ваших ответов сработали бы, если бы список каждый раз был в одном и том же порядке, но это не так. формат, однако, всегда будет оставаться неизменным. Решением является простая итерация с использованием цикла foreach, а затем проверка, начинается ли она с определенного слова, а именно слова, которое я ищу, например, Имя, Шаблон и т. Д.

Вероятно, не самый эффективный способ сделать это, но это C # для уровня чайников. Действительно блеклый уровень.

Вот моя красавица.

                foreach (string subfilter in filter.Split(';')) //filter.Split is a string [] which can be iterated through
                {
                    if (subfilter.ToUpper().StartsWith("PATTERN"))
                    {
                        pattern = subfilter.Split('=')[1];
                    }
                    if (subfilter.ToUpper().StartsWith("START"))
                    {
                        startDate = subfilter.Split('=')[1];
                    }
                    if (subfilter.ToUpper().StartsWith("END"))
                    {
                        endDate = subfilter.Split('=')[1];
                    }
                }
0 голосов
/ 20 марта 2012

Используйте это:

String filter = "name=Default;pattern=%%;start=Last;end=Now";
var parts = filter.Split(';').Select(x => x.Split('='))
                             .Where(x => x.Length == 2)
                             .Select(x => new {key = x[0], value=x[1]});
string name = "";
string pattern = "";
string start = "";
string end = "";
foreach(var part in parts)
{
    switch(part.key)
    {
        case "name":
            name = part.value;
            break;
        case "pattern":
            pattern = part.value;
            break;
        case "start":
            start = part.value;
            break;
        case "end":
            end = part.value;
            break;
    }
}

Если вам не нужны значения в именованных переменных, вам нужна только вторая строка.Он возвращает перечислимое с парами ключ / значение.

Мое решение имеет дополнительные преимущества, заключающиеся в том, что порядок этих пар ключ / значение в строке не имеет значения, и он молча игнорирует недопустимые части вместо сбоя.

0 голосов
/ 20 марта 2012

Вы можете использовать следующее:

 String filter = "name=Default;pattern=%%;start=Last;end=Now";
 string[] parts = filter.Split(';');

 string Name = parts[0].Substring(parts[0].IndexOf('=') + 1);
 string Pattern = parts[1].Substring(parts[1].IndexOf('=') + 1);
 string start = parts[2].Substring(parts[2].IndexOf('=') + 1);
 string end = parts[3].Substring(parts[3].IndexOf('=') + 1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...