Linq - Order by number then letters

前端 未结 2 764
野趣味
野趣味 2020-12-16 03:19

I have a list of strings, and these strings contain numbers and words.

What I wanted to do is order it by the numbers (numeric order) followed by the words (alphabet

2条回答
  •  生来不讨喜
    2020-12-16 04:00

    Given that you're doing it all in-process (as you've got a ToList call) I think I'd just use a custom comparer:

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

    Where AlphaNumericComparer implements IComparer, something like this:

    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);
    }
    

    You could use a giant conditional for the latter part:

    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);
    }
    

    ... but in this case I don't think I would :)

提交回复
热议问题