我一直在使用以下类别:
var query = _cityRepository.GetAll(
.OrderBy(item => item.RowKey.Substring(0, 4))
.ThenBy(item => item.ShortTitle)
但是我遇到了问题,因为我的ShortTitle看起来像这样:
Liverpool - 1
Liverpool - 2
...
Liverpool - 9
Liverpool - 10
Liverpool - 11
West Kirby - 1
West Kirby - 8
West Kirby - 12
当我使用LINQ对它进行排序时,它按顺序
Liverpool - 1
Liverpool - 11
Liverpool - 12
Liverpool - 2
West Kirby - 1
West Kirby - 12
West Kirby - 8
ShortTitle总是一串单词,后跟一个连字符,然后是一个数字。
有没有办法可以正确排序?
答案 0 :(得分:16)
试试这个
List<string> list = new List<string>() {
"Liverpool - 1",
"Liverpool - 11",
"Liverpool - 12",
"Liverpool - 2",
"West Kirby - 1",
"West Kirby - 12",
"West Kirby - 8" };
var sortedList = list.CustomSort().ToArray();
public static class MyExtensions
{
public static IEnumerable<string> CustomSort(this IEnumerable<string> list)
{
int maxLen = list.Select(s => s.Length).Max();
return list.Select(s => new
{
OrgStr = s,
SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, char.IsDigit(m.Value[0]) ? ' ' : '\xffff'))
})
.OrderBy(x => x.SortStr)
.Select(x => x.OrgStr);
}
}
答案 1 :(得分:9)
这是因为你将它们排序为字符串,而字符串11则排在第2位之前。你需要解析ShortTitle
来给你(我假设)int
的值。结束,并按此排序。
您的LINQ查询可以更改为此以使其正常工作:
var query = _cityRepository.GetAll(
.OrderBy(item => item.RowKey.Substring(0, 4))
.ThenBy(item => item.ShortTitle.Split('-').First())
.ThenBy(item => Convert.ToInt16(item.ShortTitle.Split().Last()));
答案 2 :(得分:3)
class Program
{
static void Main(string[] args)
{
var list = new[] {"Liverpool - 1",
"Liverpool - 11",
"Liverpool - 123",
"Liverpool - 342",
"Liverpool - 2"};
foreach (var x in list.OrderBy(s => Int32.Parse(Regex.Match(s, @"- (\d*)").Groups[1].Value)))
Console.WriteLine(x);
}
}
答案 3 :(得分:1)
晚会,但我不会让那阻止我!
捎带@ NominSim的好解决方案:
var query = _cityRepository.GetAll()
.Select(item =>
{
var fields = item.ShortTitle.Split('-');
return new
{
Key = item.RowKey.Substring(0,4),
Title = fields[0].Trim(),
Index = Convert.ToInt16(fields[1])
}
})
.OrderBy(item => item.Key)
.ThenBy(item => item.Title)
.ThenBy(item => item.Index);
实际上,主要区别在于捕获拆分的结果,这样我们就不必再次进行拆分来获取索引,然后我在Title中添加了一个Trim()。
答案 4 :(得分:0)
您可以创建自己的Comparer并将其传递给OrderBy或ThenBy,让它们按照您想要的方式排序。
例如,这个非常原始的比较器将在转换字符串之前用0填充最后一个数字:
class MyComparer:Comparer<string>
{
public override int Compare(string x, string y)
{
var xL = xparts[xparts.Length - 1];
long xN;
if (long.TryParse(xL,out xN))
{
xparts[xparts.Length - 1] = xN.ToString().PadLeft(20,'0');
}
var yL = yparts[yparts.Length - 1];
long yN;
if (long.TryParse(yL, out yN))
{
yparts[yparts.Length - 1] = yN.ToString().PadLeft(20, '0');
}
var x2=String.Join(" ", xparts);
var y2 = String.Join(" ", yparts);
return x2.CompareTo(y2);
}
}
你可以用最小的改变来调用它:
var query = _cityRepository.GetAll(
.OrderBy(item => item.RowKey.Substring(0, 4))
.ThenBy(item => item.ShortTitle, new MyComparer());