按字母数字排序列表,带小数

时间:2015-04-16 08:58:01

标签: c# regex winforms list sorting

我有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
等。

我在正则表达式中遗漏了什么吗?或者有更好的方法来实现这一目标吗?

5 个答案:

答案 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)

Arion's answer

为基础
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)
           );
});