开发者

Linq OrderBy GetHashCode?

ok, lets see if i can explain this.

i have a List<Games> _Games = new List<Games>(); which containts 870 Games.

i have a Title ( each page will have a diffrent title, which is not related to t开发者_JS百科he games, but the page will have the same game count ).

now, what i want to do, is order the games, based by the title i provide.

i actually tried to do something like this:

_Games = _Games.OrderByDescending(g => Math.Abs(Title.GetHashCode()));

but the order of the games stays the same.

Anyone has an idea how this kind of sorting can be created?

EDIT: you can see something similar to what i try to acheive here : Game/Quote of the day - how to?

but the accpeted answer there returns only 1 game, i want to return all the games.

EDIT: Sample title's : "Hello World", "Goodbye" === Diffrent Titles...

EDIT: this was conceptual.. added _Games = so you wont fixate on small things like that and avoiding my real question.


Your ordering attempt has two problems:

1.) You try to order by a fixed value (the hash code of the title) - ordering is internally done by most sort routines by comparing two items and positioning them accordingly. Now if you project each item to a fixed value they all are coming up as equal and no sort order can be established.

2.) You are not re-assigning the results of your ordering to your collection. You probably want something like

_Games = _Games.OrderByDescending(g => g.Title).ToList();

Edit:

Judging by your comments you just want to shuffle the list of games using a random sequence that will always be the same for a given title. If so, you can use a Fisher-Yates Shuffle combined with a Random instance that you pass the hash code of the title:

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length-1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}

Then you can use it like this:

Random rng = new Random(Title.GetHashCode());
_Games = _Games.Shuffle(rng).ToList();

Keep in mind though that hash codes are not guaranteed to be stable, they can differ between platforms (.NET 32 vs 64 bit) and on each run time of your executable - it is only guaranteed that the same title will produce the same hash code within one execution of your program. If this is a problem for you, you might have to switch to your own method of determining a unique value for each title, i.e.:

Random rng = new Random(GetUniqueValue(Title));


Your code is effectivily saying:

_Games.OrderByDescending(1);

Because the number in Title.GetHashCode() does not change for each game, thus there is no ordering applied on the items. From your description, it is unclear how you want the order of the _Games items to change for each page. Typically, you would do something along the lines of:

_query = _Games.OrderByDescending(g => Math.Abs(g.Title.GetHashCode()));

But, you don't show how Title is related to the Game itself to know if this makes sense.


I don't know Linq very well, but here's my guess. It probably doesn't even compile, but I think the general idea might be what you're after...

Random r = new Random(Title.GetHashCode());
Dictionary<object, int> map = new Dictionary<object, int>(_Games.Count);
foreach( object game in _Games )
{
    map.Add(game, r.nextInt());
}
_Games = _Games.OrderByDescending( g => map[g] );

This will give you a consistent ordering for each title, and the ordering should be different between titles. (In some cases two different titles might share an ordering but it'll be rare.)

Edit: Forgot to give _Games a consistent pre-order before applying the random sort... (Note: This algorithm has infinite slowdown potential depending on how the sort is implemented, but with only 850 games I doubt you'll see a problem)

Also, the pre-order could be more stable if _Game has a better attribute to sort on like a .Title() of it's own...

Edit2: Looks like Linq does some interesting optimizations when the variable isn't passed in, looks like a mapping is needed...


OrderByDescending is a pure method, i.e. it doesn't change the enumerable it is called on. You need to assign the return value to a variable.


I do not have an access to my development machine so cant try prctically. Plz try using

Games.OrderByDescending(g=>g.GameName.GetHashCode()+PageTitle.GetHashCode())

or

Games.OrderByDescending(g=>(g.GameName+Title).GetHashCode())

One thing that I can conclude from your requirement is you need to setup a relationship between your list items(games) with any custom logic that will generate same value for each page(page specific value will be same). without linking your list with custom logic will not give you a list that you are looking for. So you will any how bring g into the play along with your custom logic.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜