Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - Convert a string of Key value pair separated by '=' to Dictionary

Tags:

arrays

string

c#

I'm extracting data from an API which gives me some information in JSON. However, one of the values gives me:

{X0=80,X1=80,X2=80,X3=80,X4=80,X5=80,X6=80,X7=80,X8=80,X9=80,X10=80,X11=80,X12=80,X13=80,X14=80,X15=80,X16=80,X17=80,X18=80,X19=80,X20=80,X21=80,X22=80,X23=80,X24=80,X25=80,X26=80,X27=80,X28=80,X29=80,X30=80,X31=80,X32=80,X33=80,X34=80,X35=80,X36=80,X37=80,X38=80,X39=80,X40=80,X41=80,X42=80,X43=80,X44=80,X45=80,X46=80,X47=80,X48=80,X49=80,X50=80,X51=80,X52=80,X53=80,X54=80,X55=80,X56=80,X57=80,X58=80,X59=80,X60=80,X61=80,X62=80}

I am trying to decode this for use in a C# Console Application (.NET). My main question is, what would be the best way to extract this string into a dictionary or array? I am not sure if I have worded this correctly, so please correct me if I'm wrong!

Thanks!

like image 879
kpjVideo Avatar asked Jul 02 '18 23:07

kpjVideo


1 Answers

You can use Linq with Trim, Split, Select, ToDictionary

var result = json.Trim('{', '}')
                 .Split(',')
                 .Select(x => x.Split('='))
                 .ToDictionary(x => x[0], x => int.Parse(x[1]));

Console.WriteLine(string.Join("\r\n", result.Select(x => x.Key + " : " + x.Value)));

Full Demo Here

And just because i'm bored

Benchmarks

Mode             : Release (64Bit)
Test Framework   : .NET Framework 4.7.1

Operating System : Microsoft Windows 10 Pro
Version          : 10.0.17134

CPU Name         : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
Description      : Intel64 Family 6 Model 58 Stepping 9

Cores (Threads)  : 4 (8)      : Architecture  : x64
Clock Speed      : 3901 MHz   : Bus Speed     : 100 MHz
L2Cache          : 1 MB       : L3Cache       : 8 MB

Benchmarks Runs : Inputs (1) * Scales (3) * Benchmarks (3) * Runs (100) = 900

Results

--- Random Set ----------------------------------------------------------------------
| Value       |   Average |   Fastest |      Cycles |    Garbage | Test |      Gain |
--- Scale 100 -------------------------------------------------------- Time 0.229 ---
| Split       |  0.058 ms |  0.043 ms |     207,064 |  48.000 KB | Base |    0.00 % |
| JsonReplace |  0.077 ms |  0.064 ms |     273,556 |  24.000 KB | Pass |  -32.38 % |
| Regex       |  0.270 ms |  0.235 ms |     950,504 |  80.000 KB | Pass | -364.87 % |
--- Scale 1,000 ------------------------------------------------------ Time 0.633 ---
| Split       |  0.490 ms |  0.446 ms |   1,718,180 | 495.102 KB | Base |    0.00 % |
| JsonReplace |  0.671 ms |  0.596 ms |   2,352,043 | 195.078 KB | Pass |  -36.86 % |
| Regex       |  2.544 ms |  2.293 ms |   8,897,994 | 731.125 KB | Pass | -419.00 % |
--- Scale 10,000 ----------------------------------------------------- Time 5.005 ---
| Split       |  5.247 ms |  4.673 ms |  18,363,748 |   4.843 MB | Base |    0.00 % |
| JsonReplace |  6.782 ms |  5.488 ms |  23,721,593 |   1.829 MB | Pass |  -29.25 % |
| Regex       | 31.840 ms | 27.008 ms | 111,277,134 |   6.637 MB | Pass | -506.80 % |
-------------------------------------------------------------------------------------

Data

private string GenerateData(int scale)
{
   var ary = Enumerable.Range(0, scale)
                       .Select(x => $"X{x}={Rand.Next()}")
                       .ToList();

   return $"{{{string.Join(",", ary)}}}";
}

Split

public class Split : Benchmark<string, Dictionary<string,int>>
{
   protected override Dictionary<string,int> InternalRun()
   {
      return Input.Trim('{', '}')
                       .Split(',')
                       .Select(x => x.Split('='))
                       .ToDictionary(x => x[0], x => int.Parse(x[1]));
   }
}

Regex

Credited to emsimpson92 using Cast

public class Regex : Benchmark<string, Dictionary<string,int>>
{
   protected override Dictionary<string,int> InternalRun()
   {
      var regex = new System.Text.RegularExpressions.Regex("(?<key>[^,]+)=(?<value>[^,]+)");
      var matchCollection = regex.Matches(Input.Trim('{', '}'));
      return matchCollection.Cast<Match>()
                     .ToDictionary(
                         x => x.Groups["key"].Value,
                         x => int.Parse(x.Groups["value"].Value));
   }
}

JsonReplace

Credited to Hanzalah Adalan Modified to work with string.replace

public unsafe class JsonReplace : Benchmark<string, Dictionary<string,int>>
{
   protected override Dictionary<string,int> InternalRun()
   {
     return JsonConvert.DeserializeObject<Dictionary<string,int>>(Input.Replace("=", ":"));
   }
}

Additional Resources

String.Trim Method

Returns a new string in which all leading and trailing occurrences of a set of specified characters from the current String object are removed.

String.Split Method (String[], StringSplitOptions)

Splits a string into substrings based on the strings in an array. You can specify whether the substrings include empty array elements.

Enumerable.Select Method (IEnumerable, Func)

Projects each element of a sequence into a new form.

Enumerable.ToDictionary Method (IEnumerable, Func)

Creates a Dictionary from an IEnumerable according to a specified key selector function.

like image 83
TheGeneral Avatar answered Oct 06 '22 01:10

TheGeneral