Linq - 按数字和字母排序

9
我有一个字符串列表,这些字符串包含数字和单词。
我想要做的是按数字顺序(数值顺序)排序,然后按单词顺序(字母顺序)排序。
我的列表不包含两者混合...这里是一个例子
1, 5, 500 , LT, RT, 400 -> LINQ -> 1, 5, 400, 500, LT, RT
这是我拥有的一个示例,它可以工作,但我想知道是否有更好的编写方法?
            int results = 0;
            // Grabs all voltages
            var voltage = ActiveRecordLinq.AsQueryable<Equipment>()
                .OrderBy(x => x.Voltage)
                .Select(x => x.Voltage)
                .Distinct()
                .ToList();
            // Order by numeric
            var numberVoltage = voltage
                .Where( x => int.TryParse(x, out results))
                .OrderBy( x => Convert.ToInt32(x));
            // Then by alpha
            var letterVoltage = voltage
                .Where(x=> !String.IsNullOrEmpty(x))
                .Where(x => !int.TryParse(x, out results))
                .OrderBy(x => x);

            return numberVoltage.Union(letterVoltage)

感谢您的帮助!

你为什么一直在进行整数解析,电压不是被定义为整数吗? - Jimmy
@Jimmy - 不是的,电压并没有被定义为int类型,因为它包含一些单词,比如“LT”。在数据库中,它也被定义为字符串类型。 - ChickSentMeHighE
2个回答

18

考虑到你正在使用ToList调用,因此所有的操作都在进程内完成,我认为最好使用自定义比较器:

return ActiveRecordLinq.AsQueryable<Equipment>()
                       .Select(x => x.Voltage)
                       .Distinct()
                       .AsEnumerable() // Do the rest in-process
                       .Where(x => !string.IsNullOrEmpty(x))
                       .OrderBy(x => x, new AlphaNumericComparer())
                       .ToList();

AlphaNumericComparer 实现了 IComparer<string> 接口,类似于这样:

public int Compare(string first, string second)
{
    // For simplicity, let's assume neither is null :)

    int firstNumber, secondNumber;
    bool firstIsNumber = int.TryParse(first, out firstNumber);
    bool secondIsNumber = int.TryParse(second, out secondNumber);

    if (firstIsNumber)
    {
        // If they're both numbers, compare them; otherwise first comes first
        return secondIsNumber ? firstNumber.CompareTo(secondNumber) : -1;
    }
    // If second is a number, that should come first; otherwise compare
    // as strings
    return secondIsNumber ? 1 : first.CompareTo(second);
}

对于后半部分,您可以使用一个大的条件语句:

public int Compare(string first, string second)
{
    // For simplicity, let's assume neither is null :)

    int firstNumber, secondNumber;
    bool firstIsNumber = int.TryParse(first, out firstNumber);
    bool secondIsNumber = int.TryParse(second, out secondNumber);

    return firstIsNumber 
        ? secondIsNumber ? firstNumber.CompareTo(secondNumber) : -1;
        : secondIsNumber ? 1 : first.CompareTo(second);
}

...但在这种情况下,我不认为我会这样做 :)


7

这个解决方案尝试为每个值进行一次解析。

List<string> voltage = new List<string>() { "1", "5", "500" , "LT", "RT", "400" };

List<string> result = voltage
  .OrderBy(s =>
  {
    int i = 0;
    return int.TryParse(s, out i) ? i : int.MaxValue;
  })
  .ThenBy(s => s)
  .ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接