Parsing string with 3 hyphens C# - c#

I have string COO70-123456789-12345-1. I need to parse based on the "-" not the length of the substrings and use the parsed values. I have tried using Regular expressions but having issues.Please suggest.
Also after I have split the values I need to use each values: string A = COO70, int B = 123456789, int C = 12345, short D = 1 . How do I get it in different variables A,B,C,D.
string[] results = UniqueId.Split('-');
string A = results[0];
string B = results[1];
string C = results[2];
int k_id = Convert.ToInt32(k_id);
string D = results[3];
short seq = Convert.ToInt16(seq);

string s = "COO70-123456789-12345-1";
string[] split = s.Split('-'); //=> {"COO70", "123456789", "12345", "1"}

Use indexOf
To find everything before the first hyphen use:
string original= "COO70-123456789-12345-1";
string toFirstHyphen=original.Substring(0,original.IndexOf("-"));
Or if you want every section use split like the above example.

You can verify whether the input is formatted as you want and then split to get the parts.
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string pattern = #"(?x)^(\w+-\w+-\w+-\w+)$";
Regex reg = new Regex(pattern);
string test = "word-6798-3401-001";
if((reg.Match(test).Success))
foreach (var x in test.Split(new char[] {'-'}))
Console.WriteLine(x);
}
}

So it sounds like you first want to split it, but then store it into your values.
I would do something like this:
var myString = "COO70-123456789-12345-1";
var stringSet = myString.Split("-"); // This returns an array of values.
Now we need to verify that we receive only 4 sub strings:
if (stringSet.Count != 4)
throw Exception e; // Throw a real exception, not this
From here we need to know what order our strings should be in and assign them:
var A = stringSet[0];
var B = stringSet[1];
var C = stringSet[2];
var D = stringSet[3];
While this should answer your question as posed, I would recommend you work with stringSet differently personally.

Related

better ways to combine two array items into one string

Hello Please could you suggest better ways of writing this C# code.
Basically when NumberList has missing values between '-' I am trying to rebuild the String with default Values.
The final result should be "123-10-45-9-09"
As you can see value of "second-10" is replaced as the second item in the string.
10, 9 and 09 are filled in from the value string values.
This is the bad string which is missing some values.
string NumberList = "123--45--";
I have stored this string value in my app.config file.
string valuestring = "first-12,second-10,third-99,fourth-9,fifth-09";
protected string MissingNumberString(string Number)
{
string NumberList = "123--45--";
string valuestring = "first-12,second-10,third-99,fourth-9,fifth-09";
var companyAccountList = valuestring.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var result = NumberList.Split('-');
int counter = 0;
var builder = new System.Text.StringBuilder();
foreach (string s in companyAccountList)
{
string t = s.Substring(s.IndexOf('-') + 1);
if (string.IsNullOrEmpty(result[counter]))
builder.Append(t).Append("-");
else
{
if (companyAccountList.Length == counter)
builder.Append(result[counter]);
else
builder.Append(result[counter]).Append("-");
}
counter++;
}
return builder.ToString();
}
One way (assuming valuestring is in order and do not miss any defaults) to achieve this would be
string MissingNumber(string Number)
{
string valuestring = "first-12,second-10,third-99,fourth-9,fifth-09";
var regex = Regex.Matches(valuestring,#"(?<=-)(\d*)(?<=,)?");
var defaults = regex.Cast<Match>().Select(x=>x.Value).ToList();
var newArray = Number.Split('-').Select((x,index)=>string.IsNullOrEmpty(x)?defaults[index]:x);
return string.Join("-",newArray);
}
The code uses Regular Expression to break the ValueString and read the default values.
Regex.Matches(valuestring,#"(?<=-)(\d*)(?<=,)?");
The regular expression uses non-capturing groups to capture a number which is prefixed as by an optional "-" character and suffixed by an optional "," character.
Once the defaults are parsed into a List (assuming that the positions are in order and do not miss any values), we loop through the input string (which has been split based on delimiter), check if it is Empty, and if so, use the value from the Defaults (based on our assumption, it should have same index).
Update
Based on the comments, it looks like you other data in the original string, and hence the concerned sub-string has to be captured first.
We could update the Missing Number method as
static string MissingNumber(string Number)
{
string valuestring = "first-12,second-10,third-99,fourth-9,fifth-09";
var regexDefaultValues = Regex.Matches(valuestring,#"(?<=-)(\d*)(?<=,)?");
var defaults = regexDefaultValues.Cast<Match>().Select(x=>x.Value).ToList();
var regexNumberToParse = new Regex(#"(\d)*-(\d)*-(\d)*-(\d)*-(\d)*");
var capturedNumberFormat = regexNumberToParse.Match(Number).Value;
var newArray = capturedNumberFormat.Split('-').Select((x,index)=>string.IsNullOrEmpty(x)?defaults[index]:x);
var ValueWithDefaults = string.Join("-",newArray);
return regexNumberToParse.Replace(Number,ValueWithDefaults);
}
Demo Code

What is the best practise to extract a pattern from a string en C# and use it to create variables

Let's consider a string like this :
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA"
I'd like to end with something like that :
string C125 = "AAAAA";
string C12 = "22222";
string C16542 = "D1";
string C6 = "12AAA";
It means that I'd like to extract substrings (or whatever) that matches the pattern "C+characters:characters" (and exclude other patterns like ABCD:1234A e.g.). Then automatically create a variable that would have the 1st part of my "substring" ("C125:AAAAA" e.g.) as a name (so string C125 in that case) and the 2nd part of my substring as a value ("AAAAA" e.g.).
What would be the best practise to do that in C# ? Thx !
use a dictionary to store your values:
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA";
Dictionary<string, string> result = new Dictionary<string, string>();
myString.Split('|').ToList().ForEach(x => result.Add(x.Split(':')[0], x.Split(':')[1]));
Update - improved solution from CodesInChaos:
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA";
Dictionary<string, string> result = myString.Split('|').Select(x => x.Split(':')).ToDictionary(x => x[0], x => x[1]);
if your purpose is code-generation, you can create a StringBuilder:
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA";
var res = myString.Split('|')
.Select(s=>s.Split(':'))
.Where(arr=>arr[0][0] == 'C')
.Aggregate(new StringBuilder(),
(b, t)=>b.AppendFormat("string {0} = \"{1}\";", t[0], t[1])
.AppendLine());
output:
string C125 = "AAAAA";
string C12 = "22222";
string C16542 = "D1";
string C6 = "12AAA";
if your purpose to store values with keys, you can create a Dictionary
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA";
var D = myString.Split('|')
.Select(s=>s.Split(':'))
.Where(arr=>arr[0][0] == 'C')
.ToDictionary(arr=>arr[0], arr=>arr[1]);
output:
[C125, AAAAA]
[C12, 22222]
[C16542, D1]
[C6, 12AAA]
format of input string is not complex, so String.Split would more appropriate here, than RegEx
You can use the following regex, that will match any combination of word characters with length 1 or more that came after : .
#":(\w+)"
Note that the preceding pattern used capture grouping so for get the proper result you need to print the 1st group.
Demo
or you can use a positive look behind :
#"(?<=:)\w+"
Demo
But if you want to create a name from first part the better choice for such tasks is use a data structure like dictionary.
So you can loop over the result if following command :
Match match = Regex.Match(text, (\w+):(\w+));
And put the pairs of 1st and 2nd groups within a dictionary.
Perhaps, you could use something like this.You could simply use the string split.
string myString = "C125:AAAAA|C12:22222|C16542:D1|ABCD:1234A|C6:12AAA";
StringBuilder result=new StringBuilder();
List<string> resulttemp = myString.Split('|').ToList();
foreach (string[] temp in from v in resulttemp where v.StartsWith("C") select v.Split(':'))
{
result.Append("string ");
result.Append(temp[0]);
result.Append("=");
result.Append("\"");
result.Append(temp[1]);
result.Append("\"");
result.Append(";");
result.Append("\n");
}

string.split based on nth position of comma in c#

I have string:
string string1 = "0,11,22,33,5500,2000,9800,10,10,10,10,10,10,10,10,10,10,";
Now I have to split this string from 4th position of comma. I need to get values 5500,2000,9800 separately.
How can I split my string like this?
You can use LINQ and Skip:
var array = string1.Split(',').Skip(4).ToArray();
If you want to limit the elements of array (just want to get the 3 values):
var array = string1.Split(',').Skip(4).Take(3).ToArray();
I assume you don't know LINQ, so rember to import namespaces in order to use LINQ extension methods (if not imported):
using System.Linq;
EDIT (see comments):
var splitted = string1.Split(',');
var firstArr = splitted.Take(4);
var secondArray = splitted.Skip(4).Take(3);
var thirdArray = splitted.Skip(7);
If you want to have them like a string:
var s1 = string.Join(",", firstArray);
var s2 = string.Join(",", secondArray);
var s3 = string.Join(",", thirdArray);
.Why don't you do it like this:
string string1 = "0,11,22,33,5500,2000,9800,10,10,10,10,10,10,10,10,10,10,";
string[] parts = string1.Split(',');
As the OP asked a follow up question here is his answer:
To join the parts do it like this:
string firstPart = string.Join(",",parts.Take(4));
string secondPart = string.Join(",",parts.Skip(4).Take(3));
string thirdPart= string.Join(",",parts.Skip(7));

Parse multiple values from string c#

Suppose I have written "5 and 6" or "5+6". How can I assign 5 and 6 to two different variables in c# ?
P.S. I also want to do certain work if certain chars are found in string. Suppose I have written 5+5. Will this code do that ?
if(string.Contains("+"))
{
sum=x+y;
}
string input="5+5";
var numbers = Regex.Matches(input, #"\d+")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
Personally, I would vote against doing some splitting and regular expression stuff.
Instead I would (and did in the past) use one of the many Expression Evaluation libraries, like e.g. this one over at Code Project (and the updated version over at CodePlex).
Using the parser/tool above, you could do things like:
A simple expression evaluation then could look like:
Expression e = new Expression("5 + 6");
Debug.Assert(11 == e.Evaluate());
To me this is much more error-proof than doing the parsing all by myself, including regular expressions and the like.
You should use another name for your string than string
var numbers = yourString.Split("+");
var sum = Convert.ToInt32(numbers[0]) + Convert.ToInt32(numbers[1]);
Note: Thats an implementation without any error checking or error handling...
If you want to assign numbers from string to variables, you will have to parse string and make conversion.
Simple example, if you have text with only one number
string text = "500";
int num = int.Parse(text);
Now, if you want to parse something more complicated, you can use split() and/or regex to get all numbers and operators between them. Than you just iterate array and assign numbers to variables.
string text = "500+400";
if (text.Contains("+"))
{
String[] data = text.Split("+");
int a = int.Parse(data[0]);
int b = int.Parse(data[1]);
int res = a + b;
}
Basicly, if you have just 2 numbers and operazor between them, its ok. If you want to make "calculator" you will need something more, like Binary Trees or Stack.
Use the String.Split method. It splits your string rom the given character and returns a string array containing the value that is broken down into multiple pieces depending on the character to break, in this case, its "+".
int x = 0;
int y = 0;
int z = 0;
string value = "5+6";
if (value.Contains("+"))
{
string[] returnedArray = value.Split('+');
x = Convert.ToInt32(returnedArray[0]);
y = Convert.ToInt32(returnedArray[1]);
z = x + y;
}
Something like this may helpful
string strMy = "5&6";
char[] arr = strMy.ToCharArray();
List<int> list = new List<int>();
foreach (char item in arr)
{
int value;
if (int.TryParse(item.ToString(), out value))
{
list.Add(item);
}
}
list will contains all the integer values
You can use String.Split method like;
string s = "5 and 6";
string[] a = s.Split(new string[] { "and", "+" }, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine(a[0].Trim());
Console.WriteLine(a[1].Trim());
Here is a DEMO.
Use regex to get those value and then switch on the operand to do the calculation
string str = "51 + 6";
str = str.Replace(" ", "");
Regex regex = new Regex(#"(?<rightHand>\d+)(?<operand>\+|and)(?<leftHand>\d+)");
var match = regex.Match(str);
int rightHand = int.Parse(match.Groups["rightHand"].Value);
int leftHand = int.Parse(match.Groups["leftHand"].Value);
string op = match.Groups["operand"].Value;
switch (op)
{
case "+":
.
.
.
}
Split function maybe is comfortable in use but it is space inefficient
because it needs array of strings
Maybe Trim(), IndexOf(), Substring() can replace Split() function

Extracting data from plain text string

I am trying to process a report from a system which gives me the following code
000=[GEN] OK {Q=1 M=1 B=002 I=3e5e65656-e5dd-45678-b785-a05656569e}
I need to extract the values between the curly brackets {} and save them in to variables. I assume I will need to do this using regex or similar? I've really no idea where to start!! I'm using c# asp.net 4.
I need the following variables
param1 = 000
param2 = GEN
param3 = OK
param4 = 1 //Q
param5 = 1 //M
param6 = 002 //B
param7 = 3e5e65656-e5dd-45678-b785-a05656569e //I
I will name the params based on what they actually mean. Can anyone please help me here? I have tried to split based on spaces, but I get the other garbage with it!
Thanks for any pointers/help!
If the format is pretty constant, you can use .NET string processing methods to pull out the values, something along the lines of
string line =
"000=[GEN] OK {Q=1 M=1 B=002 I=3e5e65656-e5dd-45678-b785-a05656569e}";
int start = line.IndexOf('{');
int end = line.IndexOf('}');
string variablePart = line.Substring(start + 1, end - start);
string[] variables = variablePart.Split(' ');
foreach (string variable in variables)
{
string[] parts = variable.Split('=');
// parts[0] holds the variable name, parts[1] holds the value
}
Wrote this off the top of my head, so there may be an off-by-one error somewhere. Also, it would be advisable to add error checking e.g. to make sure the input string has both a { and a }.
I would suggest a regular expression for this type of work.
var objRegex = new System.Text.RegularExpressions.Regex(#"^(\d+)=\[([A-Z]+)\] ([A-Z]+) \{Q=(\d+) M=(\d+) B=(\d+) I=([a-z0-9\-]+)\}$");
var objMatch = objRegex.Match("000=[GEN] OK {Q=1 M=1 B=002 I=3e5e65656-e5dd-45678-b785-a05656569e}");
if (objMatch.Success)
{
Console.WriteLine(objMatch.Groups[1].ToString());
Console.WriteLine(objMatch.Groups[2].ToString());
Console.WriteLine(objMatch.Groups[3].ToString());
Console.WriteLine(objMatch.Groups[4].ToString());
Console.WriteLine(objMatch.Groups[5].ToString());
Console.WriteLine(objMatch.Groups[6].ToString());
Console.WriteLine(objMatch.Groups[7].ToString());
}
I've just tested this out and it works well for me.
Use a regular expression.
Quick and dirty attempt:
(?<ID1>[0-9]*)=\[(?<GEN>[a-zA-Z]*)\] OK {Q=(?<Q>[0-9]*) M=(?<M>[0-9]*) B=(?<B>[0-9]*) I=(?<I>[a-zA-Z0-9\-]*)}
This will generate named groups called ID1, GEN, Q, M, B and I.
Check out the MSDN docs for details on using Regular Expressions in C#.
You can use Regex Hero for quick C# regex testing.
You can use String.Split
string[] parts = s.Split(new string[] {"=[", "] ", " {Q=", " M=", " B=", " I=", "}"},
StringSplitOptions.None);
This solution breaks up your report code into segments and stores the desired values into an array.
The regular expression matches one report code segment at a time and stores the appropriate values in the "Parsed Report Code Array".
As your example implied, the first two code segments are treated differently than the ones after that. I made the assumption that it is always the first two segments that are processed differently.
private static string[] ParseReportCode(string reportCode) {
const int FIRST_VALUE_ONLY_SEGMENT = 3;
const int GRP_SEGMENT_NAME = 1;
const int GRP_SEGMENT_VALUE = 2;
Regex reportCodeSegmentPattern = new Regex(#"\s*([^\}\{=\s]+)(?:=\[?([^\s\]\}]+)\]?)?");
Match matchReportCodeSegment = reportCodeSegmentPattern.Match(reportCode);
List<string> parsedCodeSegmentElements = new List<string>();
int segmentCount = 0;
while (matchReportCodeSegment.Success) {
if (++segmentCount < FIRST_VALUE_ONLY_SEGMENT) {
string segmentName = matchReportCodeSegment.Groups[GRP_SEGMENT_NAME].Value;
parsedCodeSegmentElements.Add(segmentName);
}
string segmentValue = matchReportCodeSegment.Groups[GRP_SEGMENT_VALUE].Value;
if (segmentValue.Length > 0) parsedCodeSegmentElements.Add(segmentValue);
matchReportCodeSegment = matchReportCodeSegment.NextMatch();
}
return parsedCodeSegmentElements.ToArray();
}

Categories