开发者

Combining lists but getting unique members

I have a bit of a special requirement when combining lists. I will try to illustrate with an example. Lets say I'm working with 2 lists of GamePlayer objects. GamePlayer has a property called LastGamePlayed. A unique GamePlayer is identified through the GamePlayer.ID property. Now I'd like to combine listA and listB into one list, and if a 开发者_如何转开发given player is present in both lists I'd like to keep the value from listA.

I can't just combine the lists and use a comparer because my uniqueness is based on ID, and if my comparer checks ID I will not have control over whether it picks the element of listA or listB. I need something like:

for each player in listB
{
    if not listA.Contains(player) 
    {
        listFinal.Add(player)
    }
}

However, is there a more optimal way to do this instead of searching listA for each element in listB?

****EDIT****: Alternately, what if I wanted to choose which GamePlayer I keep based on the value of LastGamePlayed (instead of knowing that ListA takes precedence over ListB)? So I want a unique list of GamePlayer objects but for each player I want the GamePlayer object with the most recent LastGamePlayed? Basically I need a way to determine which object to keep when there are duplicate GamePlayers.


You should be able to use the linq enumerable extension Concat and Exept to achieve this.

listA.Concat(listB.Except(listA);

This will remove items in B that match A, and them add the result to A.

You will have to write an IEqualityComparer which compares by ID.

Documentation for theses methods can be found here:

MSDN Enumerable Extensions

IEqualityComparer documentation can be found here:

MSDN IEqualityComparer


Now that this has been clarified, the question is basically this:

  • Combine all elements from list A and list B, and if there are any duplicates, keep the one with the newest LastGamePlayed.

I would do this with a grouping:

var players = from p in listA.Concat(listB)
              group p by p.ID into g
              select g.OrderByDescending(x => x.LastGamePlayed).First();

If performance is an issue, there are "faster" ways to write this, but I would start with this.


You can write an O(n log n) solution by building a set from list2 then overwriting (or inserting) items with list1, then converting that set back to a list.

If the lists are already sorted, you could do it O(n) by merging by hand.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜