Лямбда-сортировка по длинным типам - PullRequest
0 голосов
/ 26 апреля 2018

Я пытаюсь выполнить сортировку, как показано ниже, но сталкиваюсь с проблемой со свойствами Start типа Long в лямбда-выражении. Когда они были типа int, это работало правильно, но мне нужно, чтобы это работало над большими значениями. Я пытался привести a.Start - b.Start к int, но это, похоже, дает неправильный результат сортировки.

Есть ли другой способ сортировки, или я должен изменить типы данных?

ranges.Sort((a, b) => a.Start - b.Start);

enter image description here

private readonly List<Range> ranges = new List<Range>();
public class Range
{
    public Range(long startEnd) : this(startEnd, startEnd)
    {
    }

    public Range(long start, long end)
    {
        if (end >= start)
        {
            Start = start;
            End = end;
        }
        else
        {
            Start = end;
            End = start;
        }
    }

    public long Start { get; private set; }
    public long End { get; private set; }

    public void Update(long newStart, long newEnd)
    {
        Start = newStart;
        End = newEnd;
    }

    public static implicit operator Range(long i)
    {
        return new Range(i);
    }
}

Ответы [ 4 ]

0 голосов
/ 26 апреля 2018

Приведение a.Start - b.Start к int, похоже, работает здесь, однако, делая это, вы подвергаете себя ошибкам переполнения (что если, например, a.Start равно 0 и b.Start равно long.MaxValue, например?). Поскольку Sort только проверяет, возвращает ли ваша лямбда положительное значение, отрицательное значение или ноль, вы можете сделать следующее:

ranges.Sort((a, b) => a.Start > b.Start ? 1 : a.Start < b.Start ? -1 : 0);

В качестве альтернативы, LINQ OrderBy работает просто отлично (и не ограничивается List с), но имейте в виду, что он возвращает новый объект, а не изменяет исходный, что может быть вам может не подойти:

ranges = ranges.OrderBy(r => r.Start).ToList()
0 голосов
/ 26 апреля 2018

Функция, которую вы передаете Sort, должна:

  • вернуть что-нибудь отрицательное, если a ноль, если a == b
  • все положительное, если a> b (например, всегда может быть 1)

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

ranges.Sort((a, b) => a.Start.CompareTo(b.Start));

Вы можете сделать то же самое сами, если хотите (хотя и без причины):

ranges.Sort((a, b) => a.Start > b.Start ? 1 : a.Start < b.Start ? -1 : 0);
0 голосов
/ 26 апреля 2018

Делегат, который вы передаете методу Sort, является Comparison<T>, который должен всегда возвращать int, независимо от типа T, который он сравнивает.

int, возвращаемый этим делегатом, должен быть:

Целое число со знаком, которое указывает относительные значения x и y, как показано в следующей таблице.

Value             Meaning

Less than 0       x is less than y.

0                x equals y.

Greater than 0   x is greater than y.

Поэтому тот факт, что он работал, когда ваш Start был int, на самом деле является чисто случайным.

Вы можете исправить свое дело, вернув своего делегата

a.Start.CompareTo(b.Start)
0 голосов
/ 26 апреля 2018

Сравнение должно возвращать int, поэтому вам нужно каким-то образом преобразовать long в int. Вы можете либо Convert.ToInt32, либо, если это может быть вне диапазона, просто вернуть -1 для любого отрицательного значения и 1 для любого положительного значения.

Другая, возможно, лучшая альтернатива - использовать метод CompareTo для одного из значений как int, так и long, что функционально эквивалентно второму варианту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...