Как можно сделать пользовательскую сортировку в LINQ с пустым указателем всегда на конце?

У меня была такая же проблема, что и я, я упорядочил порядок библиотек в последовательности, например, были java.lang.NullPointerException и javacard.lang.NullPointerException. Я сделал первую в качестве библиотеки по умолчанию, и если вам нужно использовать другую, вы можете явно указать полное имя класса.

16
задан ahsteele 2 July 2010 в 06:32
поделиться

3 ответа

Передо мной нет компилятора для проверки, но я думаю что-то вроде:

x.OrderBy(i => i == null).ThenBy(i => i)
42
ответ дан 30 November 2019 в 15:47
поделиться

Как сказал Джон, вам нужно определить свой собственный Comparer, реализующий IComparer. Вот как ваш метод Compare в пользовательском компараторе хотел бы сохранить null в конце.

    public int Compare(Object x, Object y)
    {
        int retVal = 0;

        IComparable valX = x as IComparable;
        IComparable valY = y as IComparable;

        if (valX == null && valY == null)
        {
            return 0;
        }

        if (valX == null)
        { 
            return 1; 
        }
        else if (valY == null)
        {
            return -1;
        }

        return valX.CompareTo(valY);
    }
0
ответ дан 30 November 2019 в 15:47
поделиться

Вы можете написать свой собственный компаратор, который делегирует существующий для ненулевых значений, но всегда сортирует нули в конце. Примерно так:

public class NullsLastComparer<T> : IComparer<T>
{
    private readonly IComparer<T> proxy;

    public NullsLastComparer(IComparer<T> proxy)
    {
        this.proxy = proxy;
    }

    public override int Compare(T first, T second)
    {
        if (first == null && second == null)
        {
            return 0;
        }
        if (first == null)
        {
            return 1;
        }
        if (second == null)
        {
            return -1;
        }
        return proxy.Compare(first, second);
    }
}

РЕДАКТИРОВАТЬ: Несколько проблем с этим подходом:

Во-первых, он плохо работает с анонимными типами; вам может потребоваться отдельный метод расширения, чтобы он работал хорошо. Или используйте ответ Кена :)

Что еще более важно, он нарушает контракт IComparer , который указывает, что нули должны быть первыми. Лично я считаю, что это ошибка в спецификации IComparer - возможно, она должна определять, что компаратор должен обрабатывать нули, но он должен не указать, идут ли они первыми или последними ... это делает такие требования (которые совершенно разумны) невозможными для выполнения с такой точностью, как мы могли бы пожелать, и имеет всевозможные неудобные разветвления для таких вещей, как реверсивный компаратор. Можно было бы ожидать, что такая вещь полностью изменит порядок следования, но, согласно спецификации, она все равно должна поддерживать нули в начале: (

Я не думаю, что видел какие-либо реализации сортировки .NET, которые на самом деле полагаются на это , но об этом определенно стоит знать.

6
ответ дан 30 November 2019 в 15:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: