Reputation: 9306
I've got a situation where I need to sort a list of strings that contain three decimal parts in descending order from left-to-right. The real code is a dictionary of <string, object>
, but I've simplified it here as I'm in the same predicament either way.
Straight to the code:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<string> perlVersions = new List<string>();
perlVersions.Add("5.26.1_32");
perlVersions.Add("5.24.1_32");
perlVersions.Add("5.8.1_64");
perlVersions.Add("5.24.2_64");
perlVersions.Sort();
perlVersions.Reverse();
foreach (string str in perlVersions) Console.WriteLine(str);
}
}
Output:
5.8.1_64
5.26.1_32
5.24.2_64
5.24.1_32
Now, Everything works well, except that the 5.8.1_64
, due to the second part of the number being lower than all others, should be at the bottom.
Is there a special sorting trick I'm missing, or is there a way to further break apart the strings and sort on each individual element?
Upvotes: 3
Views: 1306
Reputation: 32780
Or a fully query syntax version:
var b = from v in perlVersions
let ii = v.Split(".")
.Take(2)
.Select(i => int.Parse(i)).ToArray()
orderby ii[0] descending
orderby ii[1] descending
select v;
Upvotes: 1
Reputation: 24609
Try this one
string[] separator = new string[] { "." };
var result = perlVersions
.OrderByDescending(s => int.Parse(s.Split(separator, StringSplitOptions.None)[1]))
.OrderByDescending(s => int.Parse(s.Split(separator, StringSplitOptions.None)[0]))
.ToList();
Upvotes: 2
Reputation: 7054
You can do you custom sort using Linq
To do so split your string by '.' and then extend each part with '0'
List<string> perlVersions = new List<string>();
perlVersions.Add("5.26.1_32");
perlVersions.Add("5.24.1_32");
perlVersions.Add("5.8.1_64");
perlVersions.Add("5.24.2_64");
perlVersions = perlVersions
.OrderByDescending(v => string.Concat(v.Split('.').Select(x => x.PadLeft(5, '0'))))
.ToList();
This will (temporary) convert "8" to "00008" and "24" to "00024", which make your sort working as expected.
Upvotes: 0
Reputation: 169340
You could for example split the string
and treat the different parts an integers, and then sort by these using some LINQ:
static void Main()
{
List<string> perlVersions = new List<string>();
perlVersions.Add("5.26.1_32");
perlVersions.Add("5.24.1_32");
perlVersions.Add("5.8.1_64");
perlVersions.Add("5.24.2_64");
perlVersions = perlVersions
.Select(x => x.Split(new char[] { '.' }))
.Select(x =>
{
string[] lastParts = x[2].Split(new char[] { '_' });
return new { a = Convert.ToInt32(x[0]), b = Convert.ToInt32(x[1]), c = Convert.ToInt32(lastParts[0]), d = Convert.ToInt32(lastParts[1]) };
})
.OrderBy(x => x.a).ThenBy(x => x.b).ThenBy(x => x.c).ThenBy(x => x.d)
.Select(x => string.Format("{0}.{1}.{2}_{3}", x.a, x.b, x.c, x.d))
.ToList();
perlVersions.Reverse();
foreach (string str in perlVersions) Console.WriteLine(str);
}
Upvotes: 2