目前,我正在使用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查询。
答案 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;
});
或类似的(可能在比较器类中,如果它是非平凡的)。