This question already has answers here:
How to split a string using LINQ
(4 answers)
Closed 5 years ago.
I have one string having numbers and alphabets want to split alphabets and digits in separate array using LINQ query in C# .my string is as
"abcd 00001 pqr 003 xyz abc 0009"
you could transform the string to an char array and then use the Where clause to extract the necessary information:
string g = "abcd 00001 pqr 003 xyz abc 0009";
char[] numbers = g.ToCharArray().Where(x => char.IsNumber(x)).ToArray();
char[] letters = g.ToCharArray().Where(x=> char.IsLetter(x)).ToArray();
You can do it in this way:
string a ="abcd 00001 pqr 003 xyz abc 0009";
var digits = a.Split().Where(x=> {double number; return double.TryParse(x,out number);});
var letters = a.Split().Where(x=> {double number; return !double.TryParse(x,out number);});
foreach(var a1 in digits)
{
Console.WriteLine(a1);
}
foreach(var a1 in letters)
{
Console.WriteLine(a1);
}
The idea is to try to Parse the character and if it is parsed successful then it's a number.
You can use GroupBy where the Key is a boolean that specifies if the entry is a number(Can be converted to a double) or text:
string input = "abcd 00001 pqr 003 xyz abc 0009";
double dummy;
var result = input.Split().GroupBy(i => double.TryParse(i, out dummy)).ToList();
var textArray = result.Where(i => !i.Key).SelectMany(i=> i).ToArray();
var numberArray = result.Where(i => i.Key).SelectMany(i => i.ToList()).ToArray();
Related
I have a string which consists of numbers and letters like the example below:
string strFood = "123d 4hello12";
What I want to accomplish is get all the group of numbers which is 123, 4, and 12.
I am trying to do this via LinQ but I am not getting the array results since my plan is to get the array then add them altogether which is 123 + 4 + 12 and the result is 139.
This is what I tried so far but this doesn't result to group of string or integer:
string[] strArr =
strFood .GroupBy(y => Char.IsDigit(y)).Select(y => y.ToString()).ToArray();
I also tried this one but this returns all the number in one string:
var foo = from a in strFood .ToCharArray() where Char.IsDigit(a) == true select a;
Any help would be appreciated.
I suggest using regular expressions to find all groups (matches) with aggregation via Linq:
string strFood = "123d 4hello12";
var sum = Regex
.Matches(strFood, "[0-9]+") // groups of integer numbers
.OfType<Match>()
.Select(match => int.Parse(match.Value)) // treat each group as integer
.Sum(); // sum up
If you want to obtain an array (and sum up later):
int[] result = Regex
.Matches(strFood, "[0-9]+") // groups of integer numbers
.OfType<Match>()
.Select(match => int.Parse(match.Value))
.ToArray();
...
var sum = result.Sum();
You could split your string to integers collection:
string strFood = "123d 4hello12";
var integers = new Regex(#"\D").Split(strFood)
.Where(x=>!string.IsNullOrWhiteSpace(x))
.Select(x=>int.Parse(x));
and after that sum it with:
var sum = integers.Sum(); // Result : 139
Edit after comment of #Dmitry Bychenko: with some characters, such as persian digits that won't work.
Solution: either use
new Regex(#"[^0-9+]")
or
new Regex(#"\D", RegexOptions.ECMAScript)
Just to add decimal numbers in summation, you can use this regex instead:
var str = "123d 4hello12and0.2plus.1and-1and2+8.but 1....1 a.b";
// ^^^ ^ ^^ ^^^ ^^ ^^ ^ ^ ^ ^^
var s = Regex
.Matches(str, #"-?([0-9]+|[0-9]*\.[0-9]+)")
.OfType<Match>()
.Sum(c=> double.Parse(c.Value, CultureInfo.InvariantCulture));
Result will be:
Count = 11
[0]: {123}
[1]: {4}
[2]: {12}
[3]: {0}
[4]: {.2}
[5]: {.1}
[6]: {-1}
[7]: {2}
[8]: {8}
[9]: {1}
[10]: {.1}
Sum = 149.39999999999998 //~= 149.4
var yourSum = strFood.Where(x=>Char.IsDigit(x)).Select(x=>Convert.ToInt32(x)).Sum()
This will give you the sum of all numbers in your string.
If you want just an IEnumerable of ints remove the Sum() from the end
Why don't you use a simple regular expression?
string input = "123d 4hello12";
int sum = System.Text.RegularExpressions.Regex.Matches(input, #"\d+").Cast<System.Text.RegularExpressions.Match>().Sum(m => Convert.ToInt32(m.Value));
I tried using an approach using Split and Join.
First i use Linq Select to replace non digits with a ',':
strFood.Select(ch => (Char.IsDigit(ch)) ? ch : ',');
I then use Join to turn this back into a string of the form "123,,4,,,,,12", I then Split this on "," and filter out values (using Where) which have an empty string, I then convert the string into a number e.g. "123" becomes 123 and I sum the array.
Putting this all together becomes:
var Sum = String.Join("",(strFood.Select(c => (Char.IsDigit(c)) ? c : ',')))
.Split(',').Where(c => c != "").Select(c => int.Parse(c)).Sum();
Here's a slightly shorter version using Concat:
var Sum = String.Concat(strFood.Select(ch => (Char.IsDigit(ch)) ? ch : ','))
.Split(',').Where(c => c != "").Select(c => int.Parse(c)).Sum();
This gives a result of 139
Try this:
int[] strArr = strFood.ToCharArray().Where(x=> Char.IsDigit(x)).Select(y => Convert.ToInt32(y.ToString())).ToArray();
I have a string that look like that "a,b,c,d,e,1,4,3,5,8,7,5,1,2,6.... and so on.
I am looking for the best way to split it and make it look like that:
a b c d e
1 4 3 5 8
7 5 1 2 6
Assuming, that you have a fix number of columns (5):
string Input = "a,b,c,d,e,11,45,34,33,79,65,75,12,2,6";
int i = 0;
string[][] Result = Input.Split(',').GroupBy(s => i++/5).Select(g => g.ToArray()).ToArray();
First I split the string by , character, then i group the result into chunks of 5 items and select those chunks into arrays.
Result:
a b c d e
11 45 34 33 79
65 75 12 2 6
to write that result into a file you have to
using (System.IO.StreamWriter writer =new System.IO.StreamWriter(path,false))
{
foreach (string[] line in Result)
{
writer.WriteLine(string.Join("\t", line));
}
};
So I have a string which I split in half. Now I need to compare both parts of the string and output has to be all the elements that are the same in both of them.
I noticed some people using Intersect, but I don't know why it doesn't work for me, I get really weird output if I use it.
So here is my code:
string first= "1 3 6 8 4 11 34 23 3 1 7 22 24 8"
int firstLength = first.Length;
int half = firstLength / 2;
string S1 = first.Substring(0, half);
string S2= first.Substring(half, half);
var areInCommon = S1.Intersect(S2);
Console.WriteLine("Numbers that these 2 strings have in common are: ");
foreach (int i in areInCommon)
Console.WriteLine(i);
So in this case output would be: 1, 3 and 8.
Any help would be appreciated.
You were close what you really want is arrays of the numbers not arrays of chars... you can get that with the split function.
string first= "1 3 6 8 4 11 34 23 3 1 7 22 24 8"
int firstLength = first.Length;
int half = firstLength / 2;
string S1 = first.Substring(0, half);
string S2= first.Substring(half, half);
var areInCommon = S1.Split(" ".ToArray()).Intersect(S2.Split(" ".ToArray());
Console.WriteLine("Numbers that these 2 strings have in common are: ");
foreach (var i in areInCommon)
Console.WriteLine(i);
A note about using ToArray():
I use ToArray() out of habit and the reason is that if you want to pass in parameters you can't do it without this construct. For example if the data looked like this:
string first= "1, 3, 6, 8, 4, 11, 34, 23, 3, 1, 7, 22, 24, 8"
then we would need to use
.Split(" ,".ToArray(), StringSplitOptions.RemoveEmptyEntries);
since this happens a lot, I use the .ToArray() out of habit. You can also use a new construct (eg new char [] { ' ', ',' } ) I find that more cumbersome, but probably slightly faster.
simply split both the string within an array and them compare both the strings using contains() function.
string implements IEnumerable<char>, thus, you're intersecting sequences of characters instead of strings.
You should use String.Split:
IEnumerable<string> S1 = first.Substring(0, half).Split(' ');
IEnumerable<string> S2= first.Substring(half, half).Split(' ');
And then your intersection will output the desired result.
Also, you can convert each string representation of numbers into integers (i.e. int):
IEnumerable<int> S1 = first.Substring(0, half).Split(' ').Select(s => int.Parse(s));
IEnumerable<int> S2 = first.Substring(half, half).Split(' ').Select(s => int.Parse(s));
You are converting all your characters into integers. The character '1' is not represented by the integer 1. Change your foreach to:
foreach (char i in areInCommon)
This question already has answers here:
Fast and efficient way to read a space separated file of numbers into an array?
(7 answers)
Closed 8 years ago.
I have an text file that contains data in following format
ABC DEF GHI IJk
LMN OPQ RST UVW
XYZ ABC CDE EFH
Now I want to read that input in a single dimensional array as shown below:
string[] input = { ABC,DEF,GHI,IJK,LMN,OPQ,RST,UVW,XYZ,ABC,CDE,EFH}
string str = "...";
string[] input = str.Split(' ').Split('\n');
This method will deal with different types of whitespace and newline conventions.
const char[] delimiters = new char[] {' ', '\n', '\r', '\f', '\t'};
string rawInput = "ABC DEF GHI IJK\n\nLMN\tOPQ RST UVW\n\r XYZ ABC CDE EFH";
string[] input = rawInput.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
I need help in removing letters but not words from an incoming data string. Like the following,
String A = "1 2 3A 4 5C 6 ABCD EFGH 7 8D 9";
to
String A = "1 2 3 4 5 6 ABCD EFGH 7 8 9";
You need to match a letter and ensure that there is no letter before and after. So match
(?<!\p{L})\p{L}(?!\p{L})
and replace with an empty string.
Look around assertions on regular-expresssion.info
Unicode properties on regular-expresssion.info
In C#:
string s = "1 2 3A 4 5C 6 ABCD EFGH 7 8D 9";
string result = Regex.Replace(s, #"(?<!\p{L}) # Negative lookbehind assertion to ensure not a letter before
\p{L} # Unicode property, matches a letter in any language
(?!\p{L}) # Negative lookahead assertion to ensure not a letter following
", String.Empty, RegexOptions.IgnorePatternWhitespace);
The "obligatory" Linq approach:
string[] words = A.Split();
string result = string.Join(" ",
words.Select(w => w.Any(c => Char.IsDigit(c)) ?
new string(w.Where(c => Char.IsDigit(c)).ToArray()) : w));
This approach looks if each word contains a digit. Then it filters out the non-digit chars and creates a new string from the result. Otherwise it just takes the word.
And here comes the old school:
Dim A As String = "1 2 3A 4 5C 6 ABCD EFGH 7 8D 9"
Dim B As String = "1 2 3 4 5 6 ABCD EFGH 7 8 9"
Dim sb As New StringBuilder
Dim letterCount As Integer = 0
For i = 0 To A.Length - 1
Dim ch As Char = CStr(A(i)).ToLower
If ch >= "a" And ch <= "z" Then
letterCount += 1
Else
If letterCount > 1 Then sb.Append(A.Substring(i - letterCount, letterCount))
letterCount = 0
sb.Append(A(i))
End If
Next
Debug.WriteLine(B = sb.ToString) 'prints True