开发者

Convert LINQ orderby to inplace list sort

Currently, i'm sorting a list using LINQ to objects, then doing a ToList() on the results:

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

I want to convert this to do an inplace sort, i guess using List<T>.Sort() method. If i was only ordering by one thing i'd know how to do this, however, as i'm ordering by PossibleMoveLocationOrdering (which returns an int) then by IsSameType(PML) ? (_Owner[PML] as TileFlowing).UnitsWithin : 0 which evaluates to an int, then by Randomiser.Next() (which returns a random int) i don't know how to do this.

Question: How do i write the comparison function (or is there a better method) to do an implace sort of the LINQ qu开发者_如何学Goery above.


To start with, specifying three orderby clauses is a bad idea - instead, specify multiple orderings just by using comma separation.

I'm also not keen on the idea of using Randomiser.Next() for ordering, but that's an aside.

Your LINQ query should look like this (still with Randomiser in for the moment):

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

Personally I'd just use dot notation for this:

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

To sort in place, you basically need a Comparison<T> or IComparer<T> which can test multiple things, and also an implementation which creates a comparer using properties. You can do that manually (as per Marc's code), but as it happens, I have some helper classes and extension methods in MiscUtil:

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

list.Sort(comparer);

Note that using a Randomizer here is definitely a bad idea, as it will be called on each comparison (for objects with equal first parts)... this can lead to an inconsistent comparison such that x < y < z < x.


Most commonly:

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

or similar (perhaps in a comparer class, if it is non-trivial).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜