Эффективный способ разделения строк - PullRequest
4 голосов
/ 22 мая 2010

У меня есть завершенная строка, как это

N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~~ N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:

эта строка похожа на эту

  1. Это список PO (вариантов оплаты), которые разделены ~~
  2. этот список может содержать один или несколько OP
  3. PO содержит только пары ключ-значение, разделенные :
  4. пробелы обозначены ++

Мне нужно извлечь значения для ключа «RGI» и «N».

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

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

Ответы [ 6 ]

3 голосов
/ 22 мая 2010

Не знаю, является ли он более эффективным, чем RegEx, но вот альтернатива, использующая LINQ to Objects.

KeyValuePair<string, string>[] ns = (from po in pos.Split(new string[] { "~~" }, StringSplitOptions.RemoveEmptyEntries)
                                     from op in po.Split(new string[] { "++" }, StringSplitOptions.RemoveEmptyEntries)
                                     where op.StartsWith("N:") || op.StartsWith("RGI:")
                                     let op_split = op.Split(':')
                                     select new KeyValuePair<string, string>(op_split[0], op_split[1])).ToArray();
2 голосов
/ 22 мая 2010

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

string s = "N:Pay in Cash++RGI:40++R:200++";

// Replace "++" with ","
s.Replace("++",",");

// Divide all pairs (remove empty strings)
string[] tokens = s.Split(new char[] { ':', ',' }, StringSplitOptions.RemoveEmptyEntries);

Dictionary<string, string> d = new Dictionary<string, string>();

for (int i = 0; i < tokens.Length; i += 2)
{
    string key = tokens[i];
    string value = tokens[i + 1];

    d.Add(key,value);
}
2 голосов
/ 22 мая 2010

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

1 голос
/ 22 мая 2010

Вот попытка выполнить поиск по индексу: (я предпочитаю добавленное мной решение LINQ)

string test = "N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:";
string[] parts = test.Split(new string[] { "~ ~" }, StringSplitOptions.None);            
var result = parts.Select(p => new
{
    N = p.Substring(p.IndexOf("N:") + 2,
        p.IndexOf("++") - (p.IndexOf("N:") + 2)),
    RGI = p.Substring(p.IndexOf("RGI:") + 4,
        p.IndexOf("++", p.IndexOf("RGI:")) - (p.IndexOf("RGI:") + 4))
});

Создает список из двух объектов со следующими значениями:

result = {{N = "Pay in Cash", RDI = 40}, {N = "ERedemption", RDI = 42}}

РЕДАКТИРОВАТЬ: РЕШЕНИЕ С ИСПОЛЬЗОВАНИЕМ LINQ

Я решил попробовать сделать все это с помощью LINQ, и вот что я придумал:

string test = "N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:";

 var result = test.Split(new string[] { "~ ~" }, StringSplitOptions.None).
     Select(m => m.Split(new string[] { "++" }, StringSplitOptions.None)).
     Select(p => p.Select(i => i.Split(':')).
         Where(o => o[0].Equals("N") || o[0].Equals("RGI")).
         Select(r => new { Key = r[0], Value = r[1]}));

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

result = {{{Key = "N", Value = "Pay in Cash"}, {Key = "RDI", Value = 40}},
          {{Key = "N", Value = "ERedemption"}, {Key = "RDI", Value = 42}}}

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

1 голос
/ 22 мая 2010

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

 static void Main(string[] args)
{
    string str = @"N:Pay in Cash++RGI:40++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:~ ~N:ERedemption++RGI:42++R:200++T:Purchase++IP:N++IS:N++PD:PC++UCP:598.80++UPP:0.00++TCP:598.80++TPP:0.00++QE:1++QS:1++CPC:USD++PPC:Points++D:Y++E:Y++IFE:Y++AD:Y++IR:++MV:++CP:"; 
    System.Text.RegularExpressions.MatchCollection MC = System.Text.RegularExpressions.Regex.Matches(str,@"((RGI|N):.*?)\+\+");
    foreach( Match Foundmatch in MC)
    {
        string[] s = Foundmatch.Groups[1].Value.Split(':');
        Console.WriteLine("Key {0} Value {1} " ,s[0],s[1]);

    }

}
0 голосов
/ 22 мая 2010

Используйте string.Split() on ":" для извлечения пар ключ-значение.

Затем извлеките их по мере необходимости. Если позиции в строке не являются фиксированными, вам нужно искать каждый элемент в результирующем массиве string[] для конкретного ключа.

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

...