You can write a method to extract the name/value pairs from the input by returning ranges for the name and value strings, like so:
public static IEnumerable<(Range name, Range value)> ExtractNameValuePairs(string input)
{
int nameStart = 0;
int nameEnd = 0;
for (int i = 0; i < input.Length; i++)
{
switch (input[i])
{
case ' ':
nameStart = i + 1;
break;
case '=':
nameEnd = i;
break;
case ',':
yield return (new Range(nameStart, nameEnd), new Range(nameEnd + 1, i));
break;
}
}
yield return (new Range(nameStart, nameEnd), new Range(nameEnd + 1, input.Length));
}
You can then use that to parse the data into the correct parameters like so:
static void ParseUsingRangesAndCheckingNames(string input)
{
var data = new Data(); // data.Event is what?
foreach (var nvp in ExtractNameValuePairs(input))
{
switch (input[nvp.name])
{
case "tag_id" : data.TagId = input[nvp.value]; break;
case "type" : data.Type = input[nvp.value]; break;
case "frequency": data.Frequency = input[nvp.value]; break;
case "rssi" : data.Rssi = input[nvp.value]; break;
case "tx_power" : data.TxPower = input[nvp.value]; break;
case "tid" : data.Tid = input[nvp.value]; break;
}
}
}
If you know that the data will always be in the order that you specified and have all the name/value pairs from your example you can optimise that a bit to:
static void ParseUsingRanges(string input)
{
var data = new Data(); // data.Event is what?
using var iter = ExtractNameValuePairs(input).GetEnumerator();
iter.MoveNext();
data.TagId = input[iter.Current.value];
iter.MoveNext();
data.Type = input[iter.Current.value];
iter.MoveNext(); // Skip antenna
iter.MoveNext();
data.Frequency = input[iter.Current.value];
iter.MoveNext();
data.Rssi = input[iter.Current.value];
iter.MoveNext();
data.TxPower = input[iter.Current.value];
iter.MoveNext();
data.Tid = input[iter.Current.value];
}
but obviously that's a lot more brittle because it assumes the order and the presence of the various name/value pairs.
In order to benchmark this I used the following code:
using System.Text.RegularExpressions;
using BenchmarkDotNet.Attributes;
namespace Console1;
[MemoryDiagnoser]
public class Benchmarks
{
[Benchmark]
public void ParseUsingStringSplit()
{
ParseIntoDataClass(data);
}
[Benchmark]
public void ParseUsingRegExp()
{
ParseUsingRegExp(data);
}
[Benchmark]
public void ParseUsingRanges()
{
ParseUsingRanges(data);
}
[Benchmark]
public void ParseUsingRangesAndCheckingNames()
{
ParseUsingRangesAndCheckingNames(data);
}
static void ParseIntoDataClass(string eventInfo)
{
var firstArray = eventInfo.Split(',');
var secondArray = new List<string>();
var data = new Data();
foreach (var item in firstArray)
{
secondArray.Add(item.Split('=').Last());
}
for (int i = 0; i < secondArray.Count - 1; i++)
{
switch (i)
{
case 0:
data.Event = secondArray[i];
break;
case 1:
data.TagId = secondArray[i];
break;
case 2:
data.Type = secondArray[i];
break;
case 3:
data.Frequency = secondArray[i];
break;
case 4:
data.Rssi = secondArray[i];
break;
case 5:
data.TxPower = secondArray[i];
break;
case 6:
data.Tid = secondArray[i];
break;
}
}
}
static void ParseUsingRegExp(string input)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
Regex regex = new Regex(@"(\w+)\s*=\s*([^,]*)");
MatchCollection matches = regex.Matches(input);
foreach (Match match in matches)
{
parameters[match.Groups[1].Value] = match.Groups[2].Value;
}
// Data
var data = new Data();
// data.Event = ?
data.TagId = parameters["tag_id"];
data.Type = parameters["type"];
data.Frequency = parameters["frequency"];
data.Rssi = parameters["rssi"];
data.TxPower = parameters["tx_power"];
data.Tid = parameters["tid"];
}
static void ParseUsingRanges(string input)
{
var data = new Data(); // data.Event is what?
using var iter = ExtractNameValuePairs(input).GetEnumerator();
iter.MoveNext();
data.TagId = input[iter.Current.value];
iter.MoveNext();
data.Type = input[iter.Current.value];
iter.MoveNext(); // Skip antenna
iter.MoveNext();
data.Frequency = input[iter.Current.value];
iter.MoveNext();
data.Rssi = input[iter.Current.value];
iter.MoveNext();
data.TxPower = input[iter.Current.value];
iter.MoveNext();
data.Tid = input[iter.Current.value];
}
static void ParseUsingRangesAndCheckingNames(string input)
{
var data = new Data(); // data.Event is what?
foreach (var nvp in ExtractNameValuePairs(input))
{
switch (input[nvp.name])
{
case "tag_id" : data.TagId = input[nvp.value]; break;
case "type" : data.Type = input[nvp.value]; break;
case "frequency": data.Frequency = input[nvp.value]; break;
case "rssi" : data.Rssi = input[nvp.value]; break;
case "tx_power" : data.TxPower = input[nvp.value]; break;
case "tid" : data.Tid = input[nvp.value]; break;
}
}
}
public static IEnumerable<(Range name, Range value)> ExtractNameValuePairs(string input)
{
int nameStart = 0;
int nameEnd = 0;
for (int i = 0; i < input.Length; i++)
{
switch (input[i])
{
case ' ':
nameStart = i + 1;
break;
case '=':
nameEnd = i;
break;
case ',':
yield return (new Range(nameStart, nameEnd), new Range(nameEnd + 1, i));
break;
}
}
yield return (new Range(nameStart, nameEnd), new Range(nameEnd + 1, input.Length));
}
readonly string data = "event.tag.report tag_id=0x534D43010005600803251100, type=ISOC, antenna=1, frequency=919000, rssi=-451, tx_power=280, tid=0xE2003412012DF30009DA43851F0E0074300541FBFFFFDC50";
}
public class Data
{
public string? Event { get; set; }
public string? TagId { get; set; }
public string? Type { get; set; }
public string? Frequency { get; set; }
public string? Rssi { get; set; }
public string? TxPower { get; set; }
public string? Tid { get; set; }
}
With the following results:
| Method | Mean | Error | StdDev | Median | Gen0 | Allocated |
|--------------------------------- |-----------:|----------:|----------:|-----------:|-------:|----------:|
| ParseUsingStringSplit | 969.9 ns | 36.98 ns | 106.71 ns | 942.9 ns | 0.4253 | 1784 B |
| ParseUsingRegExp | 8,965.3 ns | 179.23 ns | 349.57 ns | 8,867.3 ns | 2.1362 | 8960 B |
| ParseUsingRanges | 450.8 ns | 8.92 ns | 13.62 ns | 447.3 ns | 0.1163 | 488 B |
| ParseUsingRangesAndCheckingNames | 575.3 ns | 13.24 ns | 38.19 ns | 564.2 ns | 0.1774 | 744 B |