C# - 将以'='分隔的键值对字符串转换为字典

7
我将从一个API中提取数据,该API以JSON格式给出一些信息。然而其中一个值给了我这个结果:
{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}

我正在尝试将此内容解码以在C#控制台应用程序(.NET)中使用。 我的主要问题是,提取这个字符串到一个字典或数组的最佳方法是什么?如果我的表述有误,请纠正我! 谢谢!
3个回答

16

你可以使用Linq结合TrimSplitSelectToDictionary

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

完整演示点此

仅仅因为我感到无聊

基准测试

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

结果

--- 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 % |
-------------------------------------------------------------------------------------

数据

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

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

拆分

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

正则表达式

emsimpson92使用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

这是由Hanzalah Adalan创建的,经过修改可以与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("=", ":"));
   }
}

其他资源

String.Trim 方法

返回一个新的字符串,其中从当前 String 对象中删除了一组指定字符的所有前导和尾随出现。

String.Split 方法 (String[], StringSplitOptions)

根据数组中的字符串将字符串拆分为子字符串。 您可以指定子字符串是否包括空数组元素。

Enumerable.Select 方法 (IEnumerable, Func)

将序列的每个元素投影到新表单中。

Enumerable.ToDictionary 方法 (IEnumerable, Func)

根据指定的键选择器函数从 IEnumerable 创建一个 Dictionary。


1
Var myAwesomeDictionary = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string,string>>(_yourJsonStringHere);

请问为什么它没有起作用?是因为您还没有添加Newtonsoft的NuGet包,还是出现了什么类型的异常?或者它返回了空值吗? - Hanzalah Adalan
等号,我在我的基准测试中添加了一个使用string.replace的版本。 - TheGeneral
我给你加了信用,如果你能不用替换就能使其工作,请告诉我。 - TheGeneral

1
这可以通过使用正则表达式来完成。以下模式将在两个单独的组中捕获键和值:(?<key>[^,]+)=(?<value>[^,]+)

演示

一旦你拥有了MatchCollection,就运行一个foreach循环,并将每个元素添加到字典中。

“...然后你就有两个问题了。” 但说真的,虽然这可以用正则表达式来完成,但远非最佳选择。该格式如此简单,以至于拆分字符串几乎是微不足道的。而且速度也很快。 - Corey

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