Sorting a string based array on two conditions - c#

I have an array of strings like so
May#01
April#02
Jan#03
I need to sort this first alphabetically and then by the numeric value next to the #.
Alphabetical sort is obvious but I don't seem to get the numeric part.

First order strings by their values (that will give you alphabetic sort). Then filter by integer value which is after # character:
array.OrderBy(s => s)
.ThenBy(s => Int32.Parse(s.Split('#')[1]))
Sample:
string[] array = { "May#01", "April#02", "Jan#03", "April#01" };
var query = array.OrderBy(s => s)
.ThenBy(s => Int32.Parse(s.Split('#')[1]));
Result:
"April#01"
"April#02"
"Jan#03"
"May#01"

var input = new[] { "May#01", "April#02", "Jan#03", "Jan#02", "Jan#1" };
var result = input.OrderBy(s => s.Split('#')[0])
.ThenBy(s => Int32.Parse(s.Split('#')[1]));
Result:
[
"April#02",
"Jan#1",
"Jan#02",
"Jan#03",
"May#01"
]
The other answer will produce the output:
[
"April#02",
"Jan#02",
"Jan#03",
"Jan#1",
"May#01"
]
Which I'm assuming is incorrect as Jan#02 comes before Jan#1.
You could make my code more efficient by doing the split once and storing both parts in an anonymous class, along with the original string, but I don't want to convolute the code.

Related

Array of string lengths using Linq

I have an array of strings, and I want to return an array of their lengths. Of course I could do a for loop and iterate, however I'm wondering if there's a more elegant solution, like using Linq, or some other fast/pretty one-liner.
Use the Select function to "transform" each item into another value:
var words = new[] { "some", "words", "go", "here" };
var lengths = words.Select(s => s.Length);
Using the following code:
var stringArray = new string[] {"1","12","123","1234"};
stringArray.AsParallel().ForAll(z => Console.WriteLine(z.Length));
The output should then be:
4
2
3
1

Get values from a comma separated string containing less than a value

I am attempting to compare a comma separated string against a decimal variable and find only the amounts less than my variable.
The problem I'm having is my string looks like so:
1usd,5usd,10usd,20usd
I was able to separate the string into a collection by using the comma separator and regex split, but I don't think this is the best approach since I need to check just the value and reconstruct with the us and comma seperation.
A real world example my program will be handling is
decimal changeAvil = 10
notesSet = 1usd,5usd,10usd,20usd
Result should be notesSet = 1usd,5usd
Its not the prettiest code that has ever been written, but is does the job.
I use Linq to select the prefixes of the strings that are numbers, and then compare these to the value of changeAvil.
using System;
using System.Linq;
namespace stack
{
class Program
{
static void Main(string[] args)
{
decimal changeAvil = 10;
var noteSet = "1usd,5usd,10usd,20usd";
var notes = noteSet.Split(',');
var dict =
notes.ToDictionary(
x => int.Parse(new string(x.TakeWhile(c => char.IsNumber(c))
.ToArray())), // key
x => x); // value
var selection = dict.Where(kvp => kvp.Key <= changeAvil)
.Select(kvp => kvp.Value)
.ToList();
foreach (var s in selection) {
Console.WriteLine(s);
}
}
}
}
The solution returns 1usd, 5usd, and 10usd. If your do not want 10usd to be part of the result change kvp.Key <= changeAvil to kvp.Key < changeAvil in the Where clause of the Linq expression.
You can use split command and remove the letters 'usd' and then iterate through the array and compare
decimal changeAvil = 10
notesSet = 1usd,5usd,10usd,20usd
string noteset_new = noteset.Replace('usd',''); //remove usd
string[] noteset_array = noteset_new.split[',']; //split in to array
now you can iterate the above noteset_array and do what every you want to do.
Using replace and split on the string is using two iterations through the strings characters.
A better way to get the array will be to first add a comma to the end of the string and then use split:
notesSet = 1usd,5usd,10usd,20usd
string[] noteset_array = (notesSet + ',').split['usd,']; //split in to array

C# sort string of comma separated numbers

In C# what would you consider the fastest way to do this? The code will ultimately be part of a SQL Server CLR C# user defined function, but I don't think that is important for this question.
INPUT: "1,3,2,5,4"
OUTPUT: "1,2,3,4,5"
The sorting has to be done by comparing the numbers as ints, not strings or chars.
I currently have the following but it is sorting based on strings, not ints. I could introduce a custom comparer but figure I would ask the question to see if others have any ideas before I do that.
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString udfSortDimensionValueIDString(SqlString DimensionValueIDs)
{
string[] values = ((string)DimensionValueIDs).Split(',');
Array.Sort(values);
return String.Join(",", values);
}
Using .NET 3.5 if that matters.
You can use Linq:
using System.Linq; // no include required, just uses the namespace
...
String Input = "1,3,2,5,4";
String Output = String.Join(",", Input
.Split(',')
.Select(x => int.Parse(x))
.OrderBy(x => x));
string s = "1,3,2,5,4";
string ordered = String.Join(",", s.Split(',').Select(c => Convert.ToInt32(c)).OrderBy(i=>i));
You can split the string on the commas and convert each string to a number using the Convert library. http://msdn.microsoft.com/en-us/library/bb397679.aspx

How Sort A List<string> By A Part Of That String Desc

i have a list like this :
List<string> list_lines = new List<string>();
list_lines.add("name1__pass1__com__14__55");
list_lines.add("name2__pass2__com__14__5445");
list_lines.add("name3__pass3__com__14__456456");
list_lines.add("name4__pass4__com__14__1357");
list_lines.add("name5__pass5__com__14__20000");
list_lines.add("name6__pass6__com__14__25");
list_lines.add("name7__pass7__com__14__12");
and more...
as you see there is a separator here -> "__" in every string in that list.
mean :
string[] Separator = new string[] { "__" };
foreach(string s in list_lines)
{
string[] line_ar = s.Split(Separator, StringSplitOptions.None);
int Num = int.parse(line_ar[4]);
}
i want to sort that list by Num parts of that list.
i test some methods using StackOverflow, but there was a bug in them for a big list.
would be really appreciate to help me for soting it
Asc:
list_lines = list_lines.OrderBy(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4])).ToList();
Desc:
list_lines = list_lines.OrderByDescending(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4])).ToList();
var myList = list_lines.OrderBy(x => int.Parse(x.Split(new string[] {"__"}, StringSplitOptions.None)[4])).ToList();
If the number always starts after the last underscore character, then this should work:
var sortedList = list_lines
.OrderByDescending(l => int.Parse(l.Substring(l.LastIndexOf("_") + 1)))
.ToList();
The other answers create a new list which is sorted the way you want. If instead you want the same list to be sorted, maybe try something like this:
Func<string, int> getNum = str => int.Parse(str.Split(Separator, StringSplitOptions.None)[4]);
list_lines.Sort((x, y) => getNum(x).CompareTo(getNum(y)));
This uses an overload of List<>.Sort. If you want descending order, swap x and y in the Comparison<> lambda body.
If your list is very long, this is faster (uses Quick Sort) and doesn't require the memory of a new copy of the list.
You can take advantage of lambda expression in LINQ functions like OrderBy
string[] Separator = new string[] { "__" };
var sortedList = list_lines
.OrderBy(s => int.Parse(s.Split(Separator, StringSplitOptions.None)[4]))
.ToList();
As an unrelated side note, please use correct C# naming conventions so your code is easier to read and is unified with existing C# code-base. E.g. not beginning local variable names with capital letter (Separator -> separator) and using lower camel case (Pascal case) in case it contains more words (list_lines -> listLines)
Forgive me for answering a related question here:
Sat 2020-03-21 06:03:31.129: 03: [100001] Player 1
Sat 2020-03-21 06:03:33.119: 02: [620524] Player 22
I would like to first sort the list by: 1) The number within the two [] 2) The date up until the : nn:
Here's one way (of many ways) to do it:
void Main()
{
var originalList = new List<string>
{
#"Sat 2020-03-21 06:03:31.129: 03: [100001] Player 1",
#"Sat 2020-03-21 06:03:33.119: 02: [620524] Player 22",
};
var sortableList = originalList.Select(x => splitTheLine(x));
var result = sortableList.OrderBy(x => x.numberPart).ThenBy(x => x.datePart).Select(x => x.wholeString);
}
(DateTime datePart, int numberPart, string wholeString) splitTheLine(string x)
{
string[] separator = { "[", "]", ": " };
var result = x.Split(separator, StringSplitOptions.None);
return (DateTime.Parse(result[0]), int.Parse(result[3]), x );
}
I define a method splitTheLine to extract the date and number parts along with the original string. It returns a tuple. Then I use the method with the select operator of LINQ to retrieve a list with three "columns". Again with LINQ, using the OrderByand ThenByoperators I sort the list. Finally I selectonly the originial string for the result.
This solution can be shortened a lot - but at the cost of readability, as usual.

How to convert char array into int?

I am taking input from a text box. I've saved the input digits from text box to an array like this:
char[] _array = textBox1.Text.ToCharArray(0, textBox1.Text.Length);
Now I want to convert the array to an int array because I want to perform mathematical operations on each index of the array.
How can I achieve the goal?
Thanks.
You could do it with LINQ if you just want the character code of each char.
var intArrayOfText = "some text I wrote".ToCharArray().Select(x => (int)x);
or
var intArrayOfText = someTextBox.Text.ToCharArray().Select(x => (int)x);
If each character expected to be a digit, you can parse it to an int:
List<int> listOfInt = new List<int>();
_array.ToList().ForEach(v => listOfInt.Add(int.Parse(v.ToString())));
int[] _intArray = listOfInt.ToArray();
Character code value:
List<int> listOfCharValue = new List<int>();
_array.ToList().ForEach(v => listOfCharValue.Add((int)v));
int[] _charValueArray = listOfCharValue.ToArray();
You need to handle exceptions.
Assuming what I asked in my comment is true:
string[] ints = { "1", "2", "3" };
var str = ints.Select(i => int.Parse(i));
However, the above will work only if you have already validated that your input from the text box is numeric.
I've solved my problem. I used list to accomplish the task.
I stored each array index at the relative index of the list after converting each index value to int.
Using list seems more convenient way to me. :)
Thanks to all of you.

Categories

Resources