字符串分割的有效方法

4
我有一个这样完成的字符串
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”的值。

我可以通过循环来完成,但我希望有一种更有效率的方法。请帮忙解决。

编辑:从~~到~~


2
该描述与字符串不匹配。 - user24359
哪一部分存在误导性。 - Posto
你修复了~~,但是另外,KVP(键-值对)似乎是由++分隔的,而键与其值之间由:分隔(也许这就是你所说的3和4?)。空格看起来只是空格。 - user24359
6个回答

3

不知道是否比正则表达式更高效,但这里介绍一种使用 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
您可以将字符串解析为字典,然后提取您的值...
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);
}

即使 OP 要求无需循环的解决方案,但这个方法仍然 [1] 非常易于理解,[2] 在老板说“你在那里的时候也能抓取 UCP 值吗?”时仍然有效。 - egrunin

2
我认为你应该尝试使用正则表达式。由于你正在使用C#,可以查看这个方便的.NET正则表达式速查表。链接如下:this handy .NET RegEx cheat sheet

1

这里是你需要的,我使用了正则表达式,在处理适量文本时它们表现良好。

 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]);

    }

}

1
这是一个基于索引进行搜索的尝试:(我喜欢我添加的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,那么它会包含所有的键和它们的值。


0

使用 string.Split() 函数以 ":" 为分隔符提取键值对。

然后根据需要进行提取。如果字符串中的位置不固定,则需要在结果为 string[] 的数组中搜索特定的键。

如果您需要经常搜索,建议将键值对拆分并放入某种字典中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接