string strArr="5,3,8,1,9,2,0,6,4,7";
I would like to rearrange the order of the numbers so the result will look like the following:
string result ="0,1,2,3,4,5,6,7,8,9";
Any idea?
Split, sort and join:
string[] nums = strArr.Split(',');
Array.Sort(nums);
string result = String.Join(",", nums);
Or:
string result =
String.Join(",",
strArr.Split(',')
.OrderBy(s => s)
.ToArray()
);
If you have a string with larger numbers that need to be sorted numerically, you can't sort them as strings, as for example "2" > "1000". You would convert each substring to a number, sort, and then convert them back:
string result =
String.Join(",",
strArr
.Split(',')
.Select(s => Int32.Parse(s))
.OrderBy(n => n)
.Select(n => n.ToString())
.ToArray()
);
Or, as mastoj suggested, parse the strings in the sorting:
string result =
String.Join(",",
strArr
.Split(',')
.OrderBy(s => Int32.Parse(s))
.ToArray()
);
Shorter version of one of the versions in Guffa's answer:
var res = String.Join(",", str.Split(',').OrderBy(y => int.Parse(y)).ToArray());
By splitting and joining:
string strArr = "5,3,8,1,9,2,0,6,4,7";
string[] sArr = strArr.Split(',');
Array.Sort(sArr);
string result = string.Join(",", sArr);
You can create a string array with the string.split(char[]) method.
With this array you can call the Array.Sort(T) method, that will sort the items into ascending numerical order (for your example).
With this sorted array you can call the String.Join(string, object[]) to pull it together into a string again.
string arr = "5,3,8,1,9,2,0,6,4,7";
string result = arr.Split(',').OrderBy(str => Int32.Parse(str)).Aggregate((current, next) => current + "," + next);
Related
I have a problem about sorting array after reading all decimal numbers and integers from txt file. The file contains both decimal and integer values.
These values can be splited non-fixed space.
Here is my file like this
-12,56 76
11
-6,5 43
15
...
The result is shown like
-12,56 -6,5 11 15 76 ...
How can I do the process.
You can try Linq, SelectMany since single line can contain several numbers:
var numbers = File
.ReadLines(#"c:\myfile.txt")
.SelectMany(line => line.Split(
new char[] {' ', '\t'},
StringSplitOptions.RemoveEmptyEntries))
.Select(item => decimal.Parse(item)) //TODO: Ensure the correct Culture
.OrderBy(item => item)
.ToArray(); // Let's have numbers as an array
string result = string.Join(Environment.NewLine, numbers);
Please, note StringSplitOptions.RemoveEmptyEntries when Splitting - we remove unwanted empty chunks when processing lines like "-12,56 76"
Edit: If you want to try to detect where do we have and integer and where is decimal:
var numbers = File
.ReadLines(#"c:\myfile.txt")
.SelectMany(line => line.Split(
new char[] {' ', '\t'},
StringSplitOptions.RemoveEmptyEntries))
.Select(item => {
// if we succeed in parsing as int, it's int otherwise - decimal
bool isInt = int.TryParse(item, out var intValue);
return new {
isInteger = isInt,
integerValue = intValue,
decimalValue = decimal.Parse(item) //TODO: ensure right culture
};
}) //TODO: Ensure the correct Culture
.OrderBy(item => item.decimalValue)
.ToArray(); // Let's have numbers as an array
Now if you want integer values:
int[] ints = numbers
.Where(item => item.isInteger)
.Select(item => item.integerValue)
//.OrderBy(item => item) // uncomment, if you want to sort ints
.ToArray();
For decimals:
decimal[] decimals = numbers
.Where(item => !item.isInteger)
.Select(item => item.decimalValue)
//.OrderBy(item => item) // uncomment, if you want to sort decimals
.ToArray();
This answer is mostly the same as Dmitry's, but since it's written and it's slightly different, I figured I share.
Since the file contains both decimal and integer values, and an array can only contain one type, it makes sense to obtain an array of decimal values (since all integers can be converted to a decimal).
To split the file on all whitespace characters, we can pass an empty char[] to the Split method, which allows us to use File.ReadAllText, since it will split on the newline character(s) as well:
var result = File.ReadAllText(#"f:\public\temp\temp.txt")
.Split(new char[] {}, StringSplitOptions.RemoveEmptyEntries)
.Select(decimal.Parse)
.OrderBy(i => i)
.ToList();
It sounds like you want to be able to tell which items are integer values from this array, which we can do using the modulus operator (which returns the remainder of dividing one number by another). If a decimal number divided by 1 has no remainder, then it's an integer, so:
var integerValues = result.Where(item => item % 1 == 0).ToList();
var decimalValues = result.Where(item => item % 1 != 0).ToList();
I currently have a string that looks like this:
string numbers = "55;9;20;3";
How would i make the numbers in ascending order like this:
string numbers = "3;9;20;55";
You can try with a combination of String.Join, OrderBy and int.Parse like the following:
numbers= String.Join(";",
numbers.Split(';').OrderBy(x=> int.Parse(x)));
You can check this working example as well
You can use System.Linq namespace for this:
using System.Linq;
...
string numbers = "55;9;20;3";
string output = String.Join(",", numbers.Split(';').Select(x => int.Parse(x)).OrderBy(x => x));
I'd break this into a four step process.
// 1) Split the numbers apart using based on the delimiting character ';'
var splitString = numbers.Split(';');
// 2) Convert the array of `string` to an array of `int`
var numberArray = splitString.Select(x => int.Parse(x));
// 3) Order the array which has been output by the `Split` method.
var orderedArray = numberArray.OrderBy(x => x);
// 4) Join the string back together again in the correct order, delimited by ';'
var orderedNumbers = string.Join(";", orderedArray);
This could be squashed together into less lines of code, but by doing it in multiple stages it should give you a good understanding of what is happening.
For example, Here is the same logic in one line of code:
string orderedNumers = string.Join(";", numbers.Split(';').OrderBy(x => int.Parse(x)));
I'm trying to find a way to split a string by its letters and numbers but I've had luck.
An example:
I have a string "AAAA000343BBB343"
I am either needing to split it into 2 values "AAAA000343" and "BBB343" or into 4 "AAAA" "000343" "BBB" "343"
Any help would be much appreciated
Thanks
Here is a RegEx approach to split your string into 4 values
string input = "AAAA000343BBB343";
string[] result = Regex.Matches(input, #"[a-zA-Z]+|\d+")
.Cast<Match>()
.Select(x => x.Value)
.ToArray(); //"AAAA" "000343" "BBB" "343"
So you can use regex
For
"AAAA000343" and "BBB343"
var regex = new Regex(#"[a-zA-Z]+\d+");
var result = regex
.Matches("AAAA000343BBB343")
.Cast<Match>()
.Select(x => x.Value);
// result outputs: "AAAA000343" and "BBB343"
For
4 "AAAA" "000343" "BBB" "343"
See #fubo answer
Try this:
var numAlpha = new Regex("(?<Alpha>[a-zA-Z]*)(?<Numeric>[0-9]*)");
var match = numAlpha.Match("codename123");
var Character = match.Groups["Alpha"].Value;
var Integer = match.Groups["Numeric"].Value;
I have multiple IDs in a List<string>()
List<string> IDList = new List<string>() {
"ID101", //101
"I2D102", //102
"103", //103
"I124D104", //104
"ID-105", //105
"-1006" }; //1006
Rule: The string always ends with the id which has length 1 to n and is int only
I need to extract them to int values. But my solution doesn't work
List<int> intList = IDList.Select(x => int.Parse(Regex.Match(x, #".*\d*").Value)).ToList();
If ID is always at the end, you could use LINQ solution instead of Regex:
var query = IDList.Select(id =>
int.Parse(new string(id.Reverse()
.TakeWhile(x => char.IsNumber(x))
.Reverse().ToArray())));
The idea is to take the characters from the last till it finds no number. Whatever you get, you convert it into int. The good thing about this solution is it really represents what you specify.
Well, according to
Rule: The string always ends with the id which has length 1 to n and
is int only
the pattern is nothing but
[0-9]{1,n}$
[0-9] - ints only
{1,n} - from 1 to n (both 1 and n are included)
$ - string always ends with
and possible implementation could be something like this
int n = 5; //TODO: put actual value
String pattern = "[0-9]{1," + n.ToString() + "}$";
List<int> intList = IDList
.Select(line => int.Parse(Regex.Match(line, pattern).Value))
.ToList();
In case there're some broken lines, say "abc" (and you want to filter them out):
List<int> intList = IDList
.Select(line => Regex.Match(line, pattern))
.Where(match => match.Success)
.Select(match => int.Parse(match.Value))
.ToList();
Here's another LINQ approach which works if the number is always at the end and negative values aren't possible. Skips invalid strings:
List<int> intList = IDList
.Select(s => s.Reverse().TakeWhile(Char.IsDigit))
.Where(digits => digits.Any())
.Select(digits => int.Parse(String.Concat(digits.Reverse())))
.ToList();
( Edit: similar to Ian's approach )
This below code extract last id as integer from collection and ignore them which end with none integer value
List<int> intList = IDList.Where(a => Regex.IsMatch(a, #"\d+$") == true)
.Select(x => int.Parse(Regex.Match(x, #"\d+$").Value)).ToList();
i assume you want the last numbers :
var res = IDList.Select(x => int.Parse(Regex.Match(x, #"\d+$").Value)).ToList();
I have a string like so:
mystring = "test1, 1, anotherstring, 5, yetanother, 400";
myarray can be of varying length. What I would like to do is split the string up like so:
{"test1, 1"}
{"anotherstring, 5}
{"yetanother, 400"}
Is this possible? I tried string[] newArray = mystring.Split(',') but that splits it at every comma, and not the second comma which is what I'd like to do.
Thanks for your help
Zaps
You can use a regular expression to match two items in the string:
string[] parts =
Regex.Matches(myarray[0], "([^,]*,[^,]*)(?:, |$)")
.Cast<Match>()
.Select(m => m.Groups[1].Value)
.ToArray();
This gets the items from the first string in the array. I don't know why you have the string in an array and if you have more than one string, in that case you have to loop through them and get the items from each string.
There is no direct way to make String.Split do this.
If performance is not a concern, you can use LINQ:
var input = "test1, 1, anotherstring, 5, yetanother, 400";
string[] result = input.Split(',');
result = result.Where((s, i) => i % 2 == 0)
.Zip(result.Where((s, i) => i % 2 == 1), (a, b) => a + ", " + b)
.ToArray();
Otherwise you'll probably have to split the string manually using String.IndexOf, or using a regular expression.
Another LINQ-based solution here. (Perhaps not the most efficient, but it allows for concise code and works for grouping into arbitrary group sizes).
1) Define a new query operator, InGroupsOf:
public static IEnumerable<T[]> InGroupsOf<T>(this IEnumerable<T> parts,
int groupSize)
{
IEnumerable<T> partsLeft = parts;
while (partsLeft.Count() >= groupSize)
{
yield return partsLeft.Take(groupSize).ToArray<T>();
partsLeft = partsLeft.Skip(groupSize);
}
}
2) Second, apply it to your input:
// define your input string:
string input = "test1, 1, anotherstring, 5, yetanother, 400";
// split it, remove excessive whitespace from all parts, and group them together:
IEnumerable<string[]> pairedInput = input
.Split(',')
.Select(part => part.Trim())
.InGroupsOf(2); // <-- used here!
// see if it worked:
foreach (string[] pair in pairedInput)
{
Console.WriteLine(string.Join(", ", pair));
}
Not with Split alone, but it can certainly be achieved.
I take it that myarray is actually a string, and not an array...?
In that case, you could perhaps do something like this:
string myarray = "test1, 1, anotherstring, 5, yetanother, 400";
string[] sourceArray = myarray.Split(',');
string[] newArray = sourceArray.Select((s,i) =>
(i % 2 == 0) ? "" : string.Concat(sourceArray[i-1], ",", s).Trim()
).Where(s => !String.IsNullOrEmpty(s)).ToArray();
You could probably use a Regular Expression on the original string to replace every other comma with a different 'token', e.g. ';'
Then just call string.split on the new token instead.
Interesting question... I'd do it like this:
string input = "test1, 1, anotherstring, 5, yetanother, 400";
string pattern = #"([^,]*,[^,]*),";
string[] substrings = Regex.Split(input, pattern).Where(s => s!="").Select(s => s.Trim()).ToArray();
You get exactly what you want. Only its dirty... =P =)
using IEnumerator..
var myarray = "test1, 1, anotherstring, 5, yetanother, 400";
System.Collections.IEnumerator iEN = myarray.Split(',').GetEnumerator();
var strList = new List<string>();
while (iEN.MoveNext())
{
var first = iEN.Current;
iEN.MoveNext();
strList.Add((string)first + "," + (string)iEN.Current);
}
:)