将LINQ orderby转换为inplace list sort

时间:2011-06-13 09:20:33

标签: c# linq list sorting

目前,我正在使用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()(返回一个随机的int)我不知道该怎么做。

问题:如何编写比较函数(或者有更好的方法)来执行上面的LINQ查询。

2 个答案:

答案 0 :(得分:11)

首先,指定三个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>,以及一个使用属性创建比较器的实现。您可以手动执行此操作(根据Marc的代码),但实际上,我在MiscUtil中有一些辅助类和扩展方法:

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

list.Sort(comparer);

请注意,在这里使用Randomizer 肯定是一个坏主意,因为它会在每次比较时被调用(对于具有相同第一部分的对象)...这可能导致不一致的比较,x&lt; y&lt; z&lt; x

答案 1 :(得分:6)

最常见的是:

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

或类似的(可能在比较器类中,如果它是非平凡的)。