splitting of dynamic text in a textbox c# - c#

User will enter his details in a single textbox like the following
INPUT in a textbox
S. No. Name Age Gender Concession Status Coach Seat / Berth / WL No
Current Status Coach Seat / Berth / WL No ID Type / ID No.
1 AYAN PAL 40 Male CNF S7 49 (LB) CNF S7 49 (LB)
CS CODE
int indexof1 = strMain.IndexOf("1 ");
int indexof40 = strMain.IndexOf("40 ");
int indexofstts = strMain.IndexOf("Male ");
int effectiveindexof1 = indexof1 + "1 ".Length;
int effectiveindexof40 = indexof40 + "40 ".Length;
string pname = strMain.Substring(effectiveindexof1,indexof40-effectiveindexof1);
I use substring but it won't help here because all the information provided by user will be dynamic

You can try to split it like this
var input = "1 AYAN PAL 40 Male CNF S7 49 (LB) CNF S7 49 (LB)";
var fields = input.Split(' ');
And then just access the each element like this
string id = fields[0];
string name = fields[1];
.....
Edit: diferent count of word
var fullName = string.Empty;
int i = 0;
int number = 0;
var id = fields[i++];
while (!int.TryParse(fields[i], out number))
{
fullName += fields[i++] + " ";
}
fullName = fullName.TrimEnd();
var age = fields[i++];
var gender = fields[i++];
............

Related

How to count white space in a string based on other string

Suppose we have two string s1 and s2
s1 = "123 456 789 012 1234";
s2 = "1234567";
I want to print s2 with white space as given in string s1 . Output will be
Output = "123 456 7";
Approach with simple for loop
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
for (int i = 0; i < s1.Length && i < s2.Length; i++)
{
if (char.IsWhiteSpace(s1[i]))
{
s2 = s2.Insert(i, s1[i].ToString());
}
}
https://dotnetfiddle.net/POn5E2
You should create a loop for s2 if the character equals s1 then add character to the result. Otherwise,until there add a space to result...
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
string result = "";
int s1_index = 0;
for (int i = 0; i < s2.Length; i++)
{
if (s1[s1_index] == ' ')
while (s1[s1_index] == ' ')
{
result += ' ';
s1_index++;
}
if (s2[i] == s1[s1_index])
result += s1[s1_index];
s1_index++;
}
Console.WriteLine(result);
Simply just put a condition on number of non-whitespace characters. Not efficient solution, but it has a good idea:
string s1 = "123 456 789 012 1234";
string s2 = "1234567";
var s2Length = s2.Length;
var array = s1.TakeWhile((c, index) => s1.Substring(0, index + 1)
.Count(f => !char.IsWhiteSpace(f)) <= s2Length)
.ToArray();
var result = new string(array); //123 456 7

Find out if a list of strings contains permutations of words from another string (counter for each combination)

I didn't know exactly how to ask this question better so I will try to explain it as best as I can.
Let's say I have one list of 20 strings myList1<string> and I have another string string ToCompare. Now each of the strings in the list as well as the string ToCompare have 8 words divided by empty spaces. I want to know how many times combination of any three words from string ToCompare in any possible order is to be found in the strings of myList1<string>. For an example:
This is the list (short version - example):
string1 = "AA BB CC DD EE FF GG HH";
string2 = "BB DD EE AA HH II JJ MM";
.......
string20 = "NN OO AA RR EE BB FF KK";
string ToCompare = "BB GG AA FF CC MM RR II";
Now I want to know how many times any combination of 3 words from ToCompare string is to be found in myList1<string>. To clarify futher three words from ToCompare "BB AA CC" are found in string1 of the list thus the counter for these 3 words would be 1. Another 3 words from ToCompare "BB AA II" are found in the string2 of myList1<string> but the counter here would be also 1 because it's not the same combination of words (I have "AA" and "BB" but also "II". They are not equal). Order of these 3 words doesn't matter, that means "AA BB CC" = "BB AA CC" = "CC BB AA". I want to know how many combinations of all (any) 3 words from ToCompare are found in myList1<string>. I hope it's clear what I mean.
Any help would be appreciated, I don't have a clue how to solve this. Thanks.
Example from Vanest:
List<string> source = new List<string>();
source.Add("2 4 6 8 10 12 14 99");
source.Add("16 18 20 22 24 26 28 102");
source.Add("33 6 97 38 50 34 87 88");
string ToCompare = "2 4 6 15 20 22 28 44";
The rest of the code is exacty the same, and the result:
Key = 2 4 6, Value = 2
Key = 2 4 20, Value = 1
Key = 2 4 22, Value = 1
Key = 2 4 28, Value = 1
Key = 2 6 20, Value = 1
Key = 2 6 22, Value = 1
Key = 2 6 28, Value = 1
Key = 2 20 22, Value = 1
Key = 2 20 28, Value = 1
Key = 2 22 28, Value = 1
Key = 4 6 20, Value = 1
Key = 4 6 22, Value = 1
Key = 4 6 28, Value = 1
Key = 4 20 22, Value = 1
Key = 4 20 28, Value = 1
Key = 4 22 28, Value = 1
Key = 6 20 22, Value = 1
Key = 6 20 28, Value = 1
Key = 6 22 28, Value = 1
Key = 20 22 28, Value = 1
As you can see there are combinations which not exist in the strings, and the value of the first combination is 2 but it comes only one time in the first string
I think this should suffice your ask,
List<string> source = new List<string>();
source.Add("AA BB CC DD EE FF GG HH");
source.Add("BB DD EE AA HH II JJ MM");
source.Add("NN OO AA RR EE BB FF KK");
string ToCompare = "BB GG AA FF CC MM RR II";
string word1, word2, word3, existingKey;
string[] compareList = ToCompare.Split(new string[] { " " }, StringSplitOptions.None);
Dictionary<string, int> ResultDictionary = new Dictionary<string, int>();
for (int i = 0; i < compareList.Length - 2; i++)
{
word1 = compareList[i];
for (int j = i + 1; j < compareList.Length - 1; j++)
{
word2 = compareList[j];
for (int z = j + 1; z < compareList.Length; z++)
{
word3 = compareList[z];
source.ForEach(x =>
{
if (x.Contains(word1) && x.Contains(word2) && x.Contains(word3))
{
existingKey = ResultDictionary.Keys.FirstOrDefault(y => y.Contains(word1) && y.Contains(word2) && y.Contains(word3));
if (string.IsNullOrEmpty(existingKey))
{
ResultDictionary.Add(word1 + " " + word2 + " " + word3, 1);
}
else
{
ResultDictionary[existingKey]++;
}
}
});
}
}
}
ResultDictionary will have the 3 word combinations that occur in myList1<string> with their count of occurrences. To get the total count, retrieve and add all the value fields from ResultDictionary.
EDIT:
Below snippet produces correct result with the given input,
List<string> source = new List<string>();
source.Add("2 4 6 8 10 12 14 99");
source.Add("16 18 20 22 24 26 28 102");
source.Add("33 6 97 38 50 34 87 88");
string ToCompare = "2 4 6 15 20 22 28 44";
string word1, word2, word3, existingKey;
string[] compareList = ToCompare.Split(new string[] { " " }, StringSplitOptions.None);
string[] sourceList, keywordList;
Dictionary<string, int> ResultDictionary = new Dictionary<string, int>();
source.ForEach(x =>
{
sourceList = x.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < compareList.Length - 2; i++)
{
word1 = compareList[i];
for (int j = i + 1; j < compareList.Length - 1; j++)
{
word2 = compareList[j];
for (int z = j + 1; z < compareList.Length; z++)
{
word3 = compareList[z];
if (sourceList.Contains(word1) && sourceList.Contains(word2) && sourceList.Contains(word3))
{
existingKey = ResultDictionary.Keys.FirstOrDefault(y =>
{
keywordList = y.Split(new string[] { " " }, StringSplitOptions.None);
return keywordList.Contains(word1) && keywordList.Contains(word2) && keywordList.Contains(word3);
});
if (string.IsNullOrEmpty(existingKey))
{
ResultDictionary.Add(word1 + " " + word2 + " " + word3, 1);
}
else
{
ResultDictionary[existingKey]++;
}
}
}
}
}
});
Hope this helps...
I think this will do what you're asking for:
void Main()
{
var list =
new List<String>
{
"AA BB CC DD EE FF GG HH",
"BB DD EE AA HH II JJ MM",
"NN OO AA RR EE BB FF KK"
};
var toCompare = "BB GG AA FF CC MM RR II";
var permutations = CountPermutations(list, toCompare);
}
public Int32 CountPermutations(List<String> list, String compare)
{
var words = compare.Split(' ');
return list
.Select(l => l.Split(' '))
.Select(l => new { String = String.Join(" ", l), Count = l.Join(words, li => li, wi => wi, (li, wi) => li).Count()})
.Sum(x => x.Count - 3);
}
[edit: 2/20/2019]
You can use the following to get all the matches to each list item with the total number of unique combinations
void Main()
{
var list =
new List<String>
{
"AA BB CC DD EE FF GG HH",
"BB DD EE AA HH II JJ MM",
"NN OO AA RR EE BB FF KK",
"AA AA CC DD EE FF GG HH"
};
list.Select((l, i) => new { Index = i, Item = l }).ToList().ForEach(x => Console.WriteLine($"List Item{x.Index + 1}: {x.Item}"));
var toCompare = "BB GG AA FF CC MM RR II";
Console.WriteLine($"To Compare: {toCompare}");
Func<Int32, Int32> Factorial = x => x < 0 ? -1 : x == 0 || x == 1 ? 1 : Enumerable.Range(1, x).Aggregate((c, v) => c * v);
var words = toCompare.Split(' ');
var matches = list
// Get a list of the list items with all their parts
.Select(l => new { Parts = l.Split(' '), Original = l })
// Join each part from the to-compare item to each part of the list item
.Select(l => new { String = String.Join(" ", l), Matches = l.Parts.Join(words, li => li, wi => wi, (li, wi) => li), l.Original })
// Only consider items with at least 3 matches
.Where(l => l.Matches.Count() >= 3)
// Get the each item including how many parts matched and how many unique parts there are of each part
.Select(l => new { l.Original, Matches = String.Join(" ", l.Matches), Count = l.Matches.Count(), Groups = l.Matches.GroupBy(m => m).Select(m => m.Count()) })
// To calculate the unique combinations for each match use the following mathematical equation: match_count! / (frequency_part_1! * frequency_part_2! * ... * frequency_part_n!)
.Select(l => new { l.Original, l.Matches, Combinations = Factorial(l.Count) / l.Groups.Aggregate((c, v) => c * Factorial(v)) })
.ToList();
matches.ForEach(m => Console.WriteLine($"Original: {m.Original}, Matches: {m.Matches}, Combinations: {m.Combinations}"));
var totalUniqueCombinations = matches.Sum(x => x.Combinations);
Console.WriteLine($"Total Unique Combinations: {totalUniqueCombinations}");
}

How to Split Year month Day,if Year does not exist in the given string using c#?

Here the below code am working for Split the number from the given string and stores the correspond integer into combobox.That working Perfect.But
i want to know ,If Year does not exist in the string,how to assign Year as Zero and the next integer for month strores in second combobox
For example :If string is "4Month(s)2Day(s)" Here No Year,So how to check Year not contains and insert Zero to combobox1,4 to combobox2 and 2 to combobox3
in the following code
int count = 0;
string[] delimiterChars = {"Year","Years","Years(s)","Month","Month(s)","Day","Day(s)"};
string variable =agee;
string[] words = variable.Split(delimiterChars, StringSplitOptions.None);
foreach (string s in words)
{
var data = Regex.Match(s, #"\d+").Value;
count++;
if (count == 1)
{
comboBox1.Text = data;
}
else if (count == 2)
{
comboBox2.Text = data;
}
else if (count == 3)
{
comboBox3.Text = data;
}
}
You can do with Regex like this
int combBox1, combBox2, combBox3;
var sample = "1Year(s)4month(s)2DaY(s)";
var yearString = Regex.Match(sample, #"\d+Year", RegexOptions.IgnoreCase).Value;
if (!string.IsNullOrEmpty(yearString))
combBox1 = int.Parse(Regex.Match(yearString, #"\d+").Value);
var monthString = Regex.Match(sample, #"\d+Month", RegexOptions.IgnoreCase).Value;
if (!string.IsNullOrEmpty(monthString))
combBox2 = int.Parse(Regex.Match(monthString, #"\d+").Value);
var dayStrings = Regex.Match(sample, #"\d+Day", RegexOptions.IgnoreCase).Value;
if (!string.IsNullOrEmpty(dayStrings))
combBox3 = int.Parse(Regex.Match(dayStrings, #"\d+").Value);
You can skip the int.Parse() if you want, then you have to set 0 manually.
Instead of first splitting the string and then using a RegEx to parse the parts, I'd use a RegEx for the entire work.
Using Regex Hero's tester (requires Silverlight to work...) I came up with the following:
(?:(?<years>\d+)Year\(?s?\)?)?(?<months>\d+)Month\(?s?\)?(?<days>\d+)Day\(?s?\)?
This matches all of the following inputs
Input Matching groups:
***** ****************
4Month(s)2Day(s) months: 4, days: 2
1Year(s)4Month(s)2Day(s) years: 1, months: 4, days: 2
3Years6Month(s)14Day(s) years: 3, months: 6, days: 14
1Year1Month1Day years: 1, months, 1, days: 1
As you see, it matches everything that's there. If you don't have a match for years, you can test for that with the Success property of the capture group.
Sample
var pattern = #"(?:(?<years>\d+)Year\(?s?\)?)?(?<months>\d+)Month\(?s?\)?(?<days>\d+)Day\(?s?\)?";
var regex = new Regex(pattern);
var testCases = new List<string> {
"4Month(s)2Day(s)",
"1Year(s)4Month(s)2Day(s)",
"3Years6Month(s)14Day(s)",
"1Year1Month1Day"
};
foreach (var test in testCases) {
var match = regex.Match(test);
var years = match.Groups["years"].Success ? match.Groups["years"].Value : "0";
var months = match.Groups["months"].Value;
var days = match.Groups["days"].Value;
string.Format("input: {3}, years: {0}, months: {1}, days: {2}", years, months, days, test).Dump();
}
Run that in LinqPad, and you'll see
input: 4Month(s)2Day(s), years: 0, months: 4, days: 2
input: 1Year(s)4Month(s)2Day(s), years: 1, months: 4, days: 2
input: 3Years6Month(s)14Day(s), years: 3, months: 6, days: 14
input: 1Year1Month1Day, years: 1, months: 1, days: 1
I think you have another problem here. If you split the string, you don't now if the value is a year, month or day. This information get lost with splitting. Maybe you should parse the string another way, to get this information.
You can create 3 boolean variables to check whether you have year day and month in your string, and check that boolean variable before assigning value to that combobox.
if(variable.Contains("Year"))
bool Hasyear = true;
if(variable.Contains("Month"))
bool HasMonth= true;
if(variable.Contains("Day"))
bool HasDay= true;
Use a better pattern
string input1 = "1Year(s)4Month(s)2Day(s)";
string pattern1 = #"(?'year'\d+)?(Year(\(s\))?)?(?'month'\d+)(Month(\(s\))?)?(?'day'\d+)(Day(\(s\))?)?";
Match match1 = Regex.Match(input1, pattern1);
string year1 = match1.Groups["year"].Value;
string month1 = match1.Groups["month"].Value;
string day1 = match1.Groups["day"].Value;
string input2 = "4Month(s)2Day(s)";
string pattern2 = #"(?'year'\d+)?(Year(\(s\))?)?(?'month'\d+)(Month(\(s\))?)?(?'day'\d+)(Day(\(s\))?)?";
Match match2 = Regex.Match(input2, pattern2);
string year2 = match2.Groups["year"].Value;
string month2 = match2.Groups["month"].Value;
string day2 = match2.Groups["day"].Value;​
You could very simply do like this:
string agee = "1Year4Month(s)2Day(s)";
string[] delimiterChars = {"Year", "Month", "Day"};
string variable =agee.Replace("(s)","").Replace("s", "");
string[] words = variable.Split(delimiterChars, StringSplitOptions.RemoveEmptyEntries);
int count = words.Length;
switch (count)
{
case 0:
combobox1.Text = "0";
combobox2.Text = "0";
combobox3.Text = "0";
break;
case 1:
combobox1.Text = "0";
combobox2.Text = "0";
combobox3.Text = words[0];
break;
case 2:
combobox1.Text = "0";
combobox2.Text = words[0];
combobox3.Text = words[1];
break;
case 2:
combobox1.Text = words[0];
combobox2.Text = words[1];
combobox3.Text = words[2];
break;
}

How to pull out alpha and count digits using regex?

I want to build Regex in C#. I need to know how to pull out alpha and count digits using Regex.
string example = "ASDFG 3457";
Need to pull out of "ASDFG" and then count digits (eg 4 or 5 - 7). If finding 4 digits, return value = 3457 without alpha. How to do this in C#?
I know it is better to do without regex but i have a requirement that i must use regex for a reason.
If all your doing is trying to get the numbers from a piece of text you can do this:
string expr=#"\d+";
string text="ASDFG 3457":
MatchCollection mc = Regex.Matches(text, expr);
foreach (Match m in mc)
{
Console.WriteLine(m);
}
regex
(?<alpha>\w*) (?<number>\d*)
this extracts two named groups: alpha and number.
It assumes the first group only contain words and the second only contains digits and that they are separated by a blank space.
None of them are mandatory.
If you need to make them mandatory you could replace * with +
You can also force the number of digits to four with \d{4}
I'd recommend you reading a regex tutorial and take some c# sample from the web. #Srb1313711 answer already helps you on that.
Obviously (cough) the simplest "solution" is here:
using System;
using System.Collections.Generic;
class Program
{
private static IEnumerable<long> ParseNumbers(IEnumerable<char> stream)
{
bool eos = false;
using (var it = stream.GetEnumerator())
do
{
Func<bool> advance = () => !(eos = !it.MoveNext());
while (advance() && !char.IsDigit(it.Current)) ;
if (eos) break;
long accum = 0;
do accum = accum * 10 + (it.Current - '0');
while (advance() && char.IsDigit(it.Current));
yield return accum;
}
while (!eos);
}
static void Main()
{
foreach (var num in ParseNumbers("ASDFG 3457 ASDFG.\n 123457"))
{
Console.WriteLine(num);
}
}
}
For fun, of course.
Edit
For more fun: the unsafe variation. Note this is also no longer deferred, so it won't work if not all input has arrived yet, and it generates an eager list of values:
using System;
using System.Collections.Generic;
class Program
{
private static unsafe List<long> ParseNumbers(char[] input)
{
var r = new List<long>();
fixed (char* begin = input)
{
char* it = begin, end = begin + input.Length;
while (true)
{
while (it != end && (*it < '0' || *it > '9'))
++it;
if (it == end) break;
long accum = 0;
while (it != end && *it >= '0' && *it <= '9')
accum = accum * 10 + (*(it++) - '0');
r.Add(accum);
}
}
return r;
}
static void Main()
{
foreach (var number in ParseNumbers("ASDFG 3457 ASDFG.\n 123457".ToCharArray()))
{
Console.WriteLine(number);
}
}
}
Description
This regular expression will:
capture the text into group 1
count the number of digits and place them into a capture group based on how many where found
Capture group 2 will have numbers which are 8 or more digits long
Capture group 3 will have numbers which are 5-7 digits long
Capture group 4 will have numbers which are exactly 4 digits long
Capture group 5 will have numbers which are 1-3 digits long
([A-Za-z]*) (?:(\d{8,})|(\d{5,7})|(\d{4})|(\d{1,3}))
Example
Live Demo: http://www.rubular.com/r/AIO9uUNNQc
Sample Text
ASDFG 1234567890
ASDFG 123456789
ASDFG 12345678
ASDFG 1234567
ASDFG 123456
ASDFG 12345
ASDFG 1234
ASDFG 123
ASDFG 12
ASDFG 1
Capture Groups
[0][0] = ASDFG 1234567890
[0][1] = ASDFG
[0][2] = 1234567890
[0][3] =
[0][4] =
[0][5] =
[1][0] = ASDFG 123456789
[1][1] = ASDFG
[1][2] = 123456789
[1][3] =
[1][4] =
[1][5] =
[2][0] = ASDFG 12345678
[2][1] = ASDFG
[2][2] = 12345678
[2][3] =
[2][4] =
[2][5] =
[3][0] = ASDFG 1234567
[3][1] = ASDFG
[3][2] =
[3][3] = 1234567
[3][4] =
[3][5] =
[4][0] = ASDFG 123456
[4][1] = ASDFG
[4][2] =
[4][3] = 123456
[4][4] =
[4][5] =
[5][0] = ASDFG 12345
[5][1] = ASDFG
[5][2] =
[5][3] = 12345
[5][4] =
[5][5] =
[6][0] = ASDFG 1234
[6][1] = ASDFG
[6][2] =
[6][3] =
[6][4] = 1234
[6][5] =
[7][0] = ASDFG 123
[7][1] = ASDFG
[7][2] =
[7][3] =
[7][4] =
[7][5] = 123
[8][0] = ASDFG 12
[8][1] = ASDFG
[8][2] =
[8][3] =
[8][4] =
[8][5] = 12
[9][0] = ASDFG 1
[9][1] = ASDFG
[9][2] =
[9][3] =
[9][4] =
[9][5] = 1

Distinguishing string being parsed using String Split

I need to parse a line that is in a similar format as following:
s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";
I am splitting the line with [TX] or [RX]. Here's what I do with the parsed string:
s = "Jun 21 09:47:50 ez-x5 user.debug if_comm: [TX] 02 30 20 0f 30 31 39 24 64 31 30 31 03 54 ";
string[] stringSeparators = new string[] { "[TX] " + start_key };
string transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
//At this point, transfer[] = 02 30 20 0f 30 31 39 24 64 31 30 31 03 54
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
TX_Handle(key);
}
}
stringSeparators = new string[] { "[RX]" + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
RX_Handle(key);
}
}
Basically, because I have no realistic way of comparing whether the given token is [TX] or [RX], I am forced to use the above approach to separate the string, which requires me to write essentially the same code twice.
What is a way I can get around this problem and know which token is being parsed so that I don't have to duplicate my code?
The best way to do this is look at what is common. What is common in your code? Splitting based on 2 different tokens and a function call based on 2 different tokens. This can be broken into a conditional, so, why not move the common element into a conditional?
const string receiveToken = "[RX] ";
const string transmitToken = "[TX] ";
string token = s.IndexOf(receiveToken) > -1 ? receiveToken : transmitToken;
..now you have your token, so you can remove most of the duplication.
stringSeparators = new string[] { token + start_key };
transfer = s.Split(stringSeparators, 2, StringSplitOptions.None)[1];
if (!string.IsNullOrEmpty(transfer))
{
string key = "";
string[] split = transfer.Split(' ');
if (split[0] == start_key)
{
for (int i = 0; i < key_length; i++)
{
key += split[i + Convert.ToInt32(key_index)];
}
RX_TX_Handle(key, token);
}
}
..then you can have a common handler, eg:
void RX_TX_Handle(string key, string token)
{
token == receiveToken ? RX_Handle(key) : TX_Handle(key);
}
How about a different approach and use a regular expression. Mixin a little bit of LINQ and you have some pretty easy to follow code.
static void ParseLine(
string line,
int keyIndex,
int keyLength,
Action<List<byte>> txHandler,
Action<List<byte>> rxHandler)
{
var re = new Regex(#"\[(TX|RX)\](?: ([0-9a-f]{2}))+");
var match = re.Match(line);
if (match.Success)
{
var mode = match.Groups[1].Value; // either TX or RX
var values = match.Groups[2]
.Captures.Cast<Capture>()
.Skip(keyIndex)
.Take(keyLength)
.Select(c => Convert.ToByte(c.Value, 16))
.ToList();
if (mode == "TX") txHandler(values);
else if (mode == "RX") rxHandler(values);
}
}
Or without regular expressions:
static void ParseLine(
string line,
int keyIndex,
int keyLength,
Action<List<byte>> txHandler,
Action<List<byte>> rxHandler)
{
var start = line.IndexOf('[');
var end = line.IndexOf(']', start);
var mode = line.Substring(start + 1, end - start - 1);
var values = line.Substring(end + 1)
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(keyIndex)
.Take(keyLength)
.Select(s => Convert.ToByte(s, 16))
.ToList();
if (mode == "TX") txHandler(values);
else if (mode == "RX") rxHandler(values);
}
I am not 100% sure if this answers your questions but I would create a TokenParser class that is responsible for parsing a token. You'll find it much easier to unit test.
public enum TokenType
{
Unknown = 0,
Tx = 1,
Rx = 2
}
public class Token
{
public TokenType TokenType { get; set; }
public IEnumerable<string> Values { get; set; }
}
public class TokenParser
{
public Token ParseToken(string input)
{
if (string.IsNullOrWhiteSpace(input)) throw new ArgumentNullException("input");
var token = new Token { TokenType = TokenType.Unknown };
input = input.ToUpperInvariant();
if (input.Contains("[TX]"))
{
token.TokenType = TokenType.Tx;
}
if (input.Contains("[RX]"))
{
token.TokenType = TokenType.Rx;
}
input = input.Substring(input.LastIndexOf("]", System.StringComparison.Ordinal) + 1);
token.Values = input.Trim().Split(Convert.ToChar(" "));
return token;
}
}
The example could be easily extended to allow multiple token parsers if the logic for parsing each token is vastly different.

Categories

Resources