How to separate sting with comma plus 8 digits - c#

I want to split a long string (that contains only numbers) to string arr 0f numbers with 8 digits after the comma.
for example:
input:
string str = "45.00019821162.206580920.032150970.03215097244.0031982274.245303020.014716900.046867870.000198351974.613444580.391664580.438532450.00020199 3499.19734739 0.706802871.145335320.000202002543.362378010.513759201.659094520.000202102.391733720.000483371.65957789"
output:
string[] Arr=
"
45.00019821 162.20658092 234.03215097 123123.03215097
255.00019822 74.24530302 23422.01471690 1.04686787
12.00019835 1974.61344458 234.39166458 123212.43853245
532.00020199 3499.19734739 878.70680287 1.14533532
1234.00020200 2543.36237801 23.51375920 1.65909452
12221.00020210 2.39173372 0.00048337 1.65957789"
EDIT:
I try use
String.Format("{0:0.00000000}", str);
or some SubString such as:
public static string GetSubstring(string input, int count, char delimiter)
{
return string.Join(delimiter.ToString(), input.Split(delimiter).Take(count));
}
with no success.

You can split the string using Regex:
var strRegex = #"(?<num>\d+\.\d{8})";
var myRegex = new Regex(strRegex, RegexOptions.None);
foreach (Match myMatch in myRegex.Matches(str))
{
var part = myMatch.Groups["num"].Value;
// convert 'part' to double and store it wherever you want...
}
More compact version:
var myRegex = new Regex(#"(?<num>\d*\.\d{8})", RegexOptions.None);
var myNumbers = myRegex.Matches(str).Cast<Match>()
.Select(m => m.Groups["num"].Value)
.Select(v => Convert.ToDouble(v, CultureInfo.InvariantCulture));

The input string str can be converted to the desired output as follows.
static IEnumerable<string> NumberParts(string iString)
{
IEnumerable<char> iSeq = iString;
while (iSeq.Count() > 0)
{
var Result = new String(iSeq.TakeWhile(Char.IsDigit).ToArray());
iSeq = iSeq.SkipWhile(Char.IsDigit);
Result += new String(iSeq.Take(1).ToArray());
iSeq = iSeq.Skip(1);
Result += new String(iSeq.Take(8).ToArray());
iSeq = iSeq.Skip(8);
yield return Result;
}
}
The parsing method above can be called as follows.
var Parts = NumberParts(str).ToArray();
var Result = String.Join(" ", Parts);

This would be the classical for-loop version of it, (no magic involved):
// split by separator
string[] allparts = str.Split('.');
// Container for the resulting numbers
List<string> numbers = new List<string>();
// Handle the first number separately
string start = allparts[0];
string decimalPart ="";
for (int i = 1; i < allparts.Length; i++)
{
decimalPart = allparts[i].Substring(0, 8);
numbers.Add(start + "." + decimalPart);
// overwrite the start with the next number
start = allparts[i].Substring(8, allparts[i].Length - 8);
}
EDIT:
Here would be a LINQ Version yielding the same result:
// split by separator
string[] allparts = str.Split('.');
IEnumerable<string> allInteger = allparts.Select(x => x.Length > 8 ? x.Substring(8, x.Length - 8) : x);
IEnumerable<string> allDecimals = allparts.Skip(1).Select(x => x.Substring(0,8));
string [] allWholeNumbers = allInteger.Zip(allDecimals, (i, d) => i + "." + d).ToArray();

The shortest way without regex:
var splitted = ("00000000" + str.Replace(" ", "")).Split('.');
var result = splitted
.Zip(splitted.Skip(1), (f, s) =>
string.Concat(f.Skip(8).Concat(".").Concat(s.Take(8))))
.ToList()
Try it online!

Related

Looking for next match (integer) in list of strings

I have a problem finding the next integer match in a list of strings, there are some other aspects to consider:
single string contains non relevant trailing and leading chars
numbers are formatted "D6" example 000042
there are gaps in the numbers
the list is not sorted, but it could be if there is a fast way to ignore the leading chars
Example:
abc-000001.file
aaac-000002.file
ab-002010.file
abbc-00003.file
abbbc-00004.file
abcd-00008.file
abc-000010.file
x-902010.file
The user input is 7 => next matching string would be abcd-000008.file
My attempt is :
int userInput = 0;
int counter = 0;
string found = String.Empty;
bool run = true;
while (run)
{
for (int i = 0; i < strList.Count; i++)
{
if(strList[i].Contains((userInput + counter).ToString("D6")))
{
found = strList[i];
run = false;
break;
}
}
counter++;
}
It's bad because it's slow and it can turn into a infinite loop. But I really don't know how to do this (fast).
You can parse numbers from strings with Regex and created a sorted collection which you can search with Where clause:
var strings = new[] { "abc-000001.file", "x-000004.file"};
var regP = "\\d{6}"; // simplest option in my example, maybe something more complicated will be needed
var reg = new Regex(regP);
var collection = strings
.Select(s =>
{
var num = reg.Match(s).Captures.First().Value;
return new { num = int.Parse(num), str = s};
})
.OrderBy(arg => arg.num)
.ToList();
var userInput = 2;
var res = collection
.Where(arg => arg.num >= userInput)
.FirstOrDefault()?.str; // x-000004.file
P.S.
How 9002010, 0000010, 0002010 should be treated? Cause they have 7 characters. Is it [9002010, 10, 2010] or [900201, 1, 201]?
If you don't want regex, you can do something like that:
List<string> strings = new List<string>
{
"abc-000001.file",
"aaac-000002.file",
"ab-0002010.file",
"abbc-000003.file",
"abbbc-000004.file",
"abcd-000008.file"
};
int input = 7;
var converted = strings.Select(s => new { value = Int32.Parse(s.Split('-', '.')[1]), str = s })
.OrderBy(c => c.value);
string result = converted.FirstOrDefault(v => v.value >= input)?.str;
Console.WriteLine(result);

Retrieving Numeric value before a decimal in a string value

I am working on a routine in C#
I have a list of alphanumeric sheet numbers that I would like to retrieve the numbers before the decimal to use in my routine.
FP10.01-->10
M1.01-->1
PP8.01-->8
If possible, how can something like this be achieved as either a string or integer?
You could use a regex:
Regex r = new Regex("([0-9]+)[.]");
string s = "FP10.01";
var result = Convert.ToInt32(r.Match(s).Groups[1].ToString()); //10
string input = "FP10.01";
string[] _input = input.Split('.');
string num = find(_input[0]);
public string find(string input)
{
char[] _input = input.ToArray();
int number;
string result = null;
foreach (var item in _input)
{
if (int.TryParse(item.ToString(), out number) == true)
{
result = result + number;
}
}
return result;
}
To accumulate the resulting elements into a list, you can do something like:
List<string> myList = new List<string>(){ "FP10.01","M1.01", "PP8.01"};
List<int> resultSet =
myList.Select(e =>
Regex.Replace(e.Substring(0, e.IndexOf('.')), #"[^\d]", string.Empty))
.Select(int.Parse)
.ToList();
This will take each element in myList and in turn, take a substring of each element from index 0 until before the . and then replace all the non-numeric data with string.Empty and then finally parse the string element into an int and store it into a list.
another variant would be:
List<int> resultSet =
myList.Select(e => e.Substring(0, e.IndexOf('.')))
.Select(e => string.Join(string.Empty, e.Where(char.IsDigit)))
.Select(int.Parse)
.ToList();
or if you want the elements to be strings then you could do:
List<string> resultSet =
myList.Select(e => e.Substring(0, e.IndexOf('.')))
.Select(e => string.Join(string.Empty, e.Where(char.IsDigit)))
.ToList();
To retrieve a single element of type string then you can create a helper function as such:
public static string GetValueBeforeDot(string input){
return input.Substring(0, input.IndexOf('.'))
.Where(char.IsDigit)
.Aggregate(string.Empty, (e, a) => e + a);
}
To retrieve a single element of type int then the helper function should be:
public static int GetValueBeforeDot(string input){
return int.Parse(input.Substring(0, input.IndexOf('.'))
.Where(char.IsDigit)
.Aggregate(string.Empty, (e, a) => e + a));
}
This approach removes alphabet characters by replacing them with an empty string. Splitting on the '.' character will leave you with a two element array consisting of numbers at index 0 and after decimal values at index 1.
string input = "FP10.01";
var result = Regex.Replace(input, #"([A-Za-z]+)", string.Empty).Split('.');
var beforeDecimalNumbers = result[0]; // 10
var afterDecimalNumbers = result[1]; // 01

How to modify linq index number

How do I modify the index number from an array to have a preceding 0 for number 1 - 9.
However, I would like numbers 10 on up to remain the same.
This is the raw data from debugging when getting my data from the tb1.text
"1ABC\r\n2ABC\r\3ABC\r\4ABC\r\n5ABC"
This is how I would like to store the data in my localDB.
"01ABC\r\n02ABC\r\03ABC\r\04ABC\r\n...10ABC"
Here is what I have so far.
var lines = tb1.Text.Split('\n').Select((line, index) => "YRZ"+(index + 01) + line).ToArray();
var res = string.Join("\n", lines);
Since the indexes are already part of the data entered, you need to either read it from there (and use that index) or remove it from there (and use the index you can get while Selecting). You can parse it using a regular expression. Once you have the index isolated, you can use .ToString("00") to add a leading zero.
var regex = new Regex(#"^(\d+)(.*)$");
var result = string.Join("\r\n",
tb1.Text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x =>
{
var m = regex.Match(x);
return int.Parse(m.Groups[1].Value).ToString("00") + m.Groups[2].Value;
}));
Debug.Assert("01ABC\r\n02ABC\r\n03ABC\r\n04ABC\r\n10ABC" == result);
If you only want 0 in the string why not updating it as a string:
var text = "1ABC\r\n2ABC\r\n3ABC\r\n4ABC\r\n5ABC";
var lines = text.Split('\n').ToList();
var withZero = lines.Select(
(line, i) =>
{
var newVal = i < 9 ? string.Format("0{0}", line) : line;
return newVal;
});
var result = string.Join("\n", withZero);
Or in a more concise form:
var result = string.Join("\n", text.Split('\n').Select(
(line, i) =>
{
var newVal = i < 9 ? string.Format("0{0}", line) : line;
return newVal;
}));

Read values from a textfile, delimited by = and $ signs

how can i read from a text file , from a specific location for example i have a textfile
pathA = sometexthere$
pathB = sometexthere$
pathC = sometexthere$
TimerTC = sometexthere$
I want to read everything between "=" and "$"
To read line by line i'm using this:
int counter = 0;
string line;
System.IO.StreamReader file = new System.IO.StreamReader("config.cfg");
while((line = file.ReadLine()) != null)
{
if (counter == 1)
{
label1.Text=line;
counter++;
}
else if (counter == 2)
{
label2.Text=line;
counter++;
}
}
You can use SkipWhile and TakeWhile methods:
File.ReadLines("path")
.Select(line => new string(line
.SkipWhile(c => c != '=')
.Skip(1)
.TakeWhile(c => c != '$').ToArray())).ToList();
Solution 1:
int index;
List<string> listLines = new List<string>();
foreach (var line in File.ReadLines("C:\\Data.txt"))
{
index = line.LastIndexOf('=');
listLines.Add(line.Substring(index + 1, (line.Length - index) -
((line.Length) - line.LastIndexOf('$')+1)));
}
Solution2:
you can split every line with delimter = and then extract the word starting with = ending with $
string str;
List<string> listLines = new List<string>();
foreach (var line in File.ReadLines("C:\\Data.txt"))
{
str = line.Split('=')[1].Trim();
listLines.Add(str.Substring(0, str.Length -
(str.Length - str.LastIndexOf('$'))));
}
Solution 3:
List<string> listLines = new List<string>();
foreach (var line in File.ReadLines("C:\\Data.txt"))
{
var str = line.Split(new char[] { '=', '$'},
StringSplitOptions.RemoveEmptyEntries);
listLines.Add(str[1].Trim());
}
You can also do it using a Regex (although, now you have two problems):
var regex = new Regex(
#"^ # beginning of the line
(?<key>.*?) # part before the equals sign
\s*=\s* # `=` with optional whitespace
(?<value>.*) # part after the equals sign
\$ # `$`
$ # end of the line",
RegexOptions.Multiline |
RegexOptions.IgnorePatternWhitespace |
RegexOptions.Compiled);
Or, a one liner:
var regex = new Regex(#"^(?<key>.*?)\s*=\s*(?<value>.*)\$$");
And then select matches into key-value pairs:
var keyValuePairs = File
.ReadLines("config.cfg")
.Select(line => regex.Match(line))
.Where(match => match.Success)
.Select(match => new
{
Key = match.Groups["key"].Value,
Value = match.Groups["value"].Value
})
.ToList();

How to get strings first 4 characters after first semicolon

I have a string and my requirement is that from my string I should get the first 4 characters from first semicolon(;).
I have below code:
var str1 = Settings.Default.sConstr.ToString();
var str2 = Settings.Default.dConstr.ToString();
string name = //sub string of str1 + sub string of str2;
How can we do this...?
You can use String.IndexOf and String.SubString methods like;
string s = "asdfghj;zxcvb";
var index = s.IndexOf(';');
Console.WriteLine(s.Substring(index -4, 4));
Output will be;
fghj
Here a demonstration.
If you looking 4 character AFTER semi column, you can use it like;
string s = "asdfghj;zxcvb";
var index = s.IndexOf(';');
Console.WriteLine(s.Substring(index + 1, 4));
Output will be;
zxcv
Here a demonstration.
Also checking your string contains ; character and it has 4 character after ; is a good ideas like;
if(s.Contains(';') && (s.Length >= s.IndexOf(';') + 5))
{
//Your code
}
str1.Substring(str1.IndexOf(';'), 4) + str2.Substring(str2.IndexOf(';'), 4);
or if you want 4 chars after the ; then use this one:
str1.Substring(str1.IndexOf(';') + 1, 4) + str2.Substring(str2.IndexOf(';') + 1, 4);
You can use Split() to do this.
var str1 = Settings.Default.sConstr.Split(';');
var str2 = Settings.Default.dConstr.Split(';');
string name = str1[1].Substring(0,4)+" "+str2[1].Substring(0,4);
Hope it work.
Try:
var stringToGetFrom = "some characters;Get this stuff.";
var chars = stringToGetFrom.SkipWhile(c => c != ';').Skip(1).Take(3);
// Will contain the string "Get":
var selectedString = new string(chars.ToArray());
Try this
sConstr.Split(';')[1].Substring(0,4)
Demo
string s = "asdfghj;zxcvb";
string result = s.Split(new char[]{';'})[1].Substring(0,4);
or:
string s = "asdfghj;zxcvb";
var chars = s.Split(new char[] { ';' })[1].ToCharArray().Take(4).ToArray();
string result = new string(chars);

Categories

Resources