I want to order an array containing numbers and letters in an ascending order
the values are stored as a string in a DB.
This is the list I have
4B
1A
1
1B
2
4C
4
and want them to order like this where numbers are ascending followed by letters alphabetically.
1
1A
1B
2
4
4B
4C
So far I tried
allScenes.OrderBy(x => Convert.ToInt32(x.SceneNumber)).ToList()
and
allScenes.OrderBy(x => Convert.int.parse(x.SceneNumber)).ToList()
but both don't work because of the letters after the number.
Any idea how I can make this work?
Given your example data where the first number is always a single digit:
allScenes.OrderBy(x => x.SceneNumber).ToList()
If you can possibly have multi-digit numbers, please provide them and where you want them in the sort order.
This is one way to sort multiple digit numbers:
var allScenes = new[]{
new {SceneNumber="4B"},
new {SceneNumber="1A"},
new {SceneNumber="1"},
new {SceneNumber="1B"},
new {SceneNumber="2"},
new {SceneNumber="14"},
new {SceneNumber="4C"},
new {SceneNumber="14A"},
new {SceneNumber="200"},
new {SceneNumber="200A"},
new {SceneNumber="200B"}
};
var nums="0123456789".ToCharArray();
var result=allScenes
.OrderBy(x=>x.SceneNumber.LastIndexOfAny(nums))
.ThenBy(x=>x.SceneNumber);
Results:
1
1A
1B
2
4B
4C
14
14A
200
200A
200B
The database may not be able to convert the LastIndexOfAny function to something SQL-like, so you may need to do an .ToList() before the .OrderBy():
var nums="0123456789".ToCharArray();
var result=allScenes
.ToList()
.OrderBy(x=>x.SceneNumber.LastIndexOfAny(nums))
.ThenBy(x=>x.SceneNumber);
Very simple
string[] allScenes = {"4B","1A","1","1B","2","4C"};
var result = allScenes.OrderBy(x => x.First()).ThenBy(x => x.Last());
As values are stored as string into the database you just have to write OrderBy(e=> e).
The code below proves this works:
string[] items = {"4B", "1A", "1", "1B", "2", "4C", "4"};
items.OrderBy(e=> e)
Related
My goal is to sort a List<string> in messy order to an order like this ["1", "1a", "2", "2a", "2b", "a", "b"]
My code is a little long, so I've included it at this link https://dotnetfiddle.net/wZ0dTG.
What I'm trying to do is split the strings using Regex.Split(string, "([0-9]+)")[0] then based on which strings pass int.TryParse, I sort the list numerically or alphabetically.
The regex matches all the integers contained within the string.
Until I apply the regex, it sorts. Although it sorts, it doesn't sort them properly.
When I apply the regex, I get this error:
ArgumentException: Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: 'System.Comparison`1[Ndot_Partnering_Tool.Data.Models.Project
So you have to split your strings into an (optional) numeric part and an (optional) rest. This can be done by a Regex:
var match = Regex.Match(item, #"(?<number>\d+)?(?<rest>.*)$");
The "number" part matches one or more digits, but is optional (question mark), the "rest" part matches the whole rest of the string.
Sorting via Linq:
var input = new List<string>{ "12a", "1", "1a", "2", "2a", "2b", "a", "b", "12a" };
var sorted = input.OrderBy(item =>
{
var match = Regex.Match(item, #"(?<number>\d+)?(?<rest>.*)$");
return Tuple.Create(match.Groups["number"].Success ? int.Parse(match.Groups["number"].Value) : -1, match.Groups["rest"].Value);
}).ToList();
(I deliberately decided to put the items without a leading number before the rest; this was not specified in the question).
Output: a, b, 1, 1a, 2, 2a, 2b, 12a
For this particular task the OrderBy method is perfect for you. I would use that instead of Regex.
OrderBy uses lambda expressions as a key to sort.
Since letters are after numbers in the alphabet this method is using, you can actually just sort by default.
You can do:
List<string> List = new List<string>() {"a", "2b", "1a", "1", "2", "2a", "b", "1b" };
List<string> OrderedList = List.OrderBy(x => x).ToList();
The OrderBy method returns IEnumerable so you have to convert it back to List.
Output:
The original list: a 2b 1a 1 2 2a b 1b
The ordered list: 1 1a 1b 2 2a 2b a b
Two problems:
SplitRegex() failes on argument "a" because it does not match regex (RegEx.Split returns array with one element). You can use this code:
return Regex.Split(x, "([0-9]+)").ElementAtOrDefault(1) ?? string.Empty;
When neither x nor y can be converted to integer, you call CompareString() for x and y, but x and y are not whole strings, they are only numerical parts (and because of that empty). You need to pass list items as is to comparer and extract numbers there:
bool leftcanconvertflag = Int32.TryParse(SplitRegex(x), out leftconvertresult);
bool rightcanconvertflag = Int32.TryParse(SplitRegex(y), out rightconvertresult);
if (leftcanconvertflag && !rightcanconvertflag)
{
compareresult = -1;
}
if (!leftcanconvertflag && rightcanconvertflag)
{
compareresult = 1;
}
if (leftcanconvertflag && rightcanconvertflag)
{
compareresult = leftconvertresult.CompareTo(rightconvertresult);
}
if (!leftcanconvertflag && !rightcanconvertflag)
{
compareresult = CompareString(x, y);
}
and sort list like this:
list.Sort(CompareContractNumbers);
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));
}
};
i have a winform C# sql app in which i'm retrieving data and storing in strings. like so,.
string a1 = Convert.ToString(srj[#"Sub_1"]);
string a2 = Convert.ToString(srj[#"Sub_2"]);
string a3 = Convert.ToString(srj[#"Sub_3"]);
string a4 = Convert.ToString(srj[#"Sub_4"]);
string a5 = Convert.ToString(srj[#"Sub_5"]);
string a6 = Convert.ToString(srj[#"Sub_6"]);
string a7 = Convert.ToString(srj[#"Sub_7"]);
string a8 = Convert.ToString(srj[#"Sub_8"]);
string a9 = Convert.ToString(srj[#"Sub_9"]);
string a10 = Convert.ToString(srj[#"Sub_10"]);
string a11 = Convert.ToString(srj[#"Sub_11"]);
string a12 = Convert.ToString(srj[#"Sub_12"]);
here i'm retrieving 12 values. now i want to compare each of these values with some strings like a1, a2...a29. if both the strings match the a corresponding check box with the string has to be checked.
but the way i see it, i have to compare 30 string with first value, then 30 strings with the second value, and so forth.
is there any way to do this using some other method?
Maybe you could use the Aho–Corasick string matching algorithm.
It allow you to locates elements of a finite set of strings within an input string matching all patterns from the set simultaneously.
http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm
OK - try this
String[] myList1 = new String[] {"a","ab", "ba", "cc", "ab"};
String[] myList2 = new String[] {"a","abc", "ba", "c2c", "ab1", "cccc", "ba"};
var keyResult = myList1.Where(x=>myList2.Contains(x)).ToArray();
Gives an array containing "a" and "ba". The two arrays do not have to be the same length. It also deals with repeated items as a single item.
And then there is the set intersection method as well.
var keyResult2 = myList1.Intersect(myList2).ToArray();
This question already has answers here:
2d Array from text file c# [closed]
(3 answers)
Closed 9 years ago.
How can I loop through a text file to create six arrays from the content of the text file.
For example, the text file will look like this but with more lines(without title) maybe 200 of them
top_speed average_speed cadence altitude heart_rate power
84 73 0 -124 0 50
86 179 84 -125 121 3893
It would be nice to have an array for each. So, for example
top_speed = 84 + 86 : average_speed = 73 + 179 ... (and so on)
What's the best way to do this?
Anyway, if that is homework, following code will not help you :) But if it is not homework, you will understand how to parse such files with LINQ
var items =
File.ReadAllLines(filename) // read lines from file
.Select(line => line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)
.Select(Int32.Parse)
.ToArray()) // convert each line to array of integers
.Select(values => new {
TopSpeed = values[0],
AverageSpeed = values[1],
Cadence = values[2],
Altitude = values[3],
HeartRate = values[4],
Power = values[5]
}); // create anonymous object with nice strongly-typed properties
int[] topSpeeds = items.Select(i => i.TopSpeed).ToArray();
You could create a Record class and then use a simple LINQ query:
var records = File.ReadLines("file.txt")
.Select(line =>
{
string[] parts = line.Split('\t');
return new Record
{
TopSpeed = int.Parse(parts[0]),
AverageSpeed = int.Parse(parts[1]),
Cadence = int.Parse(parts[2]),
Altitude = int.Parse(parts[3]),
HeartRate = int.Parse(parts[4]),
Power = int.Parse(parts[5])
};
}).ToArray();
This will give you a bunch of Records, one per line in the original file. If you wanted to then check all of HeartRates for building a histogram or graphing or whatever, you could grab them like this:
var allHeartRates = records.Select(rec => rec.HeartRate);
I want to try and get a line of numbers and count them and store them in an array. I want to have the user input numbers up to 100 and I want the program to be able to separate them by spaces and count them in C#
Example: 98 92 86 92 100 92 93
The spaces will be the only separator and it would count 7 grades and store them in an array but I'm not sure how to to really do this.
Not to get empty entries in case of 2 spaces
var ints = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(i => int.Parse(i))
.ToList(); //or ToArray() whichever you want
Since you want an Array on this, use Split function.
string x = "98 92 86 92 100 92 93";
string[] val = x.Split(' ');
int totalCount = val.Length;
or a better way to do this is by using LINQ which automatically converts into array of integers
string x = "98 92 86 92 100 92 93";
int[] y = x.Split(' ').Select(n => Convert.ToInt32(n)).ToArray();
int totalCount = y.Length;