English 中文(简体)
Effective way of String splitting
原标题:

I have a completed string like this

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:

this string is like this

  1. It s list of PO s(Payment Options) which are separated by ~~
  2. this list may contains one or more OP
  3. PO contains only Key-Value Pairs which separated by :
  4. spaces are denoted by ++

I need to extract the values for Key "RGI" and "N".

I can do it via for loop , I want a efficient way to do this. any help on this.

Edit: from ~ ~ To ~~

最佳回答

hear ya go I used regular expressions and for a reasonable amount of text they preform well.

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

    }

}
问题回答

Don t know if it s more efficient than RegEx, but here s a alternative using 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();

I think you should try a regular expression. Since you are using C#, check out this handy .NET RegEx cheat sheet.

You could parse the string into a dictionary and then pull in your values...

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

Here is an attempt doing a search based on index: (I prefer my LINQ solution that I added)

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

Creates a list of two objects with following values:

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

EDIT: SOLUTION USING LINQ

I decided to try and do it all with LINQ and here is what I came up with:

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

It produces and array for each item that contains a Key Value pair of only N and RGI.

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

If you want you can remove the Where and it will include all they Keys and their Values.

Use string.Split() on ":" to extract the key-value pairs.

Then extract as you need them. If the positions in the string are not fixed,you will need to search each item in the resulting string[] array for a particular key.

If you need to search often, I would consider splitting the key-value pairs and placing in some sort of Dictionary.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签