Конвертировать LINQ orderby в сортировку списка мест - PullRequest
5 голосов
/ 13 июня 2011

В настоящее время я сортирую список, используя LINQ для объектов, затем делаю ToList() для результатов:

var SortedPossibleMoveLocations = (from PML in PossibleMoveLocations
                                   orderby Randomiser.Next()
                                   orderby IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0
                                   orderby PossibleMoveLocationOrdering(PML)
                                   select PML).ToList();

Я хочу преобразовать это, чтобы сделать сортировку по месту, я думаю, используя List<T>.Sort() метод.Если бы я заказывал только одну вещь, я бы знал, как это сделать, так как я упорядочиваю по PossibleMoveLocationOrdering (что возвращает int), затем по IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0, что оценивается как int, тогдапо Randomiser.Next() (который возвращает случайное целое число) я не знаю, как это сделать.

Вопрос: Как мне написать функцию сравнения (или есть лучший метод)чтобы выполнить сортировку по типу запроса LINQ выше.

Ответы [ 2 ]

11 голосов
/ 13 июня 2011

Начать с того, что указывать три предложения orderby - плохая идея - вместо этого указывайте несколько порядков, просто используя запятую.

Я также не заинтересован в идее использования Randomiser.Next() для заказа, но это в стороне.

Ваш запрос LINQ должен выглядеть следующим образом (все еще с Randomiser на данный момент):

var query = (from PML in PossibleMoveLocations
             orderby PossibleMoveLocationOrdering(PML),
                     IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0,
                     Randomiser.Next()
             select PML).ToList();

Лично я бы просто использовал для этого точечную запись:

var query = PossibleMoveLocations
                .OrderBy(pml => PossibleMoveLocationOrdering(PML))
                .ThenBy(pml => IsSameType(pml) ? 
                                    (_Owner[pml] as TileFlowing).UnitsWithin : 0)
                .ThenBy(pml => Randomiser.Next())
                .ToList();

Для сортировки на месте вам, в основном, нужен Comparison<T> или IComparer<T>, который может тестировать несколько вещей, а также реализация, которая создает компаратор с использованием свойств. Вы можете сделать это вручную (согласно коду Марка), но, как это происходит, у меня есть несколько вспомогательных классов и методов расширения в MiscUtil :

var comparer = ProjectionComparer<PossibleMove>
                   .Create(pml => PossibleMoveLocationOrdering(PML));
                   .ThenBy(pml => IsSameType(pml) ? ...)
                   .ThenBy(...);

list.Sort(comparer);

Обратите внимание, что использование Randomizer здесь определенно плохая идея, так как она будет вызываться при каждом сравнении (для объектов с равными первыми частями) ... это может привести к противоречивому сравнению, например что x <<code>y <<code>z <<code>x.

6 голосов
/ 13 июня 2011

Чаще всего:

list.Sort((x,y) => {
    int result = /* first comparison, for example
                    string.Compare(x.Name, y.Name) */
    if (result == 0) result = /* second comparison,
                                 for example x.Id.CompareTo(y.Id) */
    ...
    if (result == 0) result = /* final comparison */
    return result;
});

или аналогичный (возможно, в классе сравнения, если он нетривиален).

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