我有List<string>
我需要按字母数字排序,但它也有一个小数。样本如下所示:
E11.9
E13.9
E10.9
E11.65
E10.65
E11.69
E13.10
E10.10
我需要的输出应该是这样的:
E10.10
E10.65
E10.9
E11.69
E11.9
等。
我已尝试过此代码:
result.Sort((s1, s2) =>
{
string pattern = "([A-Za-z])([0-9]+)";
string h1 = Regex.Match(s1, pattern).Groups[1].Value;
string h2 = Regex.Match(s2, pattern).Groups[1].Value;
if (h1 != h2)
return h1.CompareTo(h2);
string t1 = Regex.Match(s1, pattern).Groups[2].Value;
string t2 = Regex.Match(s2, pattern).Groups[2].Value;
return int.Parse(t1).CompareTo(int.Parse(t2));
});
但它似乎只是首先按字母排序,然后按小数位前的数字排序。所以这就是我得到的:
E10.9
E10.65
E10.10
E11.9
E11.69
等。
我在正则表达式中遗漏了什么吗?或者有更好的方法来实现这一目标吗?
答案 0 :(得分:6)
你能这样做吗?:
测试数据:
var ls=new List<string>
{
"E11.9",
"E13.9",
"E10.9",
"E11.65",
"E10.65",
"E11.69",
"E13.10",
"E10.10",
};
<强>的LINQ:强>
var result= ls
.OrderBy (l =>l.Substring(0,1))
.ThenBy(l =>double.Parse(l.Substring(1), CultureInfo.InvariantCulture))
.ToList();
答案 1 :(得分:2)
var result = list.OrderBy(l => l[0]).ThenBy(l => double.Parse(l.Substring(1));
首先,你要按字母排序,然后按字母后面的数字排序。如果您需要在double.Parse
中处理不同的文化设置,则必须在那里提供。请参阅MSDN on Double.Parse。
答案 2 :(得分:1)
如果格式为[single-letter][decimal-number]
,您可以执行以下操作:
var result= list.
.OrderBy(s => s.Substring(0,1))
.ThenBy(s => double.Parse(s.Substring(1), CultureInfo.InvariantCulture));
无需将正则表达式纳入故事
答案 3 :(得分:1)
这是一个没有正则表达式的LINQ解决方案:
var ordered = from str in result
let firstChar = string.IsNullOrEmpty(str) ? "" : str.Substring(0, 1)
let decimalPart = string.IsNullOrEmpty(str) ? "" : str.Substring(1)
let numOrNull = decimalPart.TryGetDecimal(NumberFormatInfo.InvariantInfo)
orderby firstChar, numOrNull ?? decimal.MaxValue ascending, str ascending
select str;
result = ordered.ToList();
使用此扩展名将子字符串解析为decimal:
public static decimal? TryGetDecimal(this string item, IFormatProvider formatProvider = null)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
decimal d = 0m;
bool success = decimal.TryParse(item, NumberStyles.Any, formatProvider, out d);
if (success)
return d;
else
return null;
}
您应该在LINQ查询中使用此扩展名而不是局部变量作为已学习的here。
答案 4 :(得分:0)
另一种具有更新的正则表达式的变体
ls.Sort((a, b) =>
{
var pattern = new Regex(@"(?<letter>[A-Za-z])(?<number>[0-9]+\.?[0-9]*)$");
var matchA = pattern.Match(a);
var matchB = pattern.Match(b);
var compareLetter = matchA.Groups["letter"].Value.CompareTo(matchB.Groups["letter"].Value);
if (compareLetter != 0) return compareLetter;
return double.Parse(matchA.Groups["number"].Value, CultureInfo.InvariantCulture).CompareTo(
double.Parse(matchB.Groups["number"].Value, CultureInfo.InvariantCulture)
);
});