Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Sorry for the vague title, but I can't describe my problem properly and shortly.

I am maintaining a list of players and their games with the following form:

gamesPerPlayer = 
  {{playerId -> playerId1, games-> {game11, game12, game13}},
   {playerId -> playerId2, games-> {game21, game22, game23, game24}}}

Each game is a complex structure of nested lists but it has a unique field, so we can simply and think that each game is just {idGame, infoGame}. Thus my list is like this

gamesPerPlayer = 
  {{playerId -> playerId1, 
      games -> {{idGame11, infoGame11}, {idGame12, infoGame12}, {idGame13, infoGame13}}},
   {playerId -> playerId2, 
      games -> {{idGame21, infoGame21}, {idGame22, infoGame22}}}

How can I write a (fast) function to join two of this lists eliminating duplicates? The order of the playerId and the games in the new list is not important.

Just to clarify, an example:

list1 = {{playerId -> 1, game s-> {{11, "info"}, {12, "info"}}},
         {playerId -> 2, games->{{21, "info"}}}};
list2 = {{playerId -> 1, games -> {{11, "info"}, {13, "info"}}},
         {playerId -> 3, games -> {{31, "info"}}}};
newList = myJoinFunction[list1, list2];

Expected result:

{{playerId -> 1, games -> {{11, "info"}, {12, "info"}, {13, "info"}}},
 {playerId -> 2, games -> {{21, "info"}}, {playerId -> 3, games -> {{31, "info"}}}
share|improve this question
1  
Related: 16450 –  Michael E2 Mar 16 at 14:09

2 Answers 2

up vote 6 down vote accepted

This looks a lot like the solution Yves came up with but I arrived at it independently:

combine[id_, tag_, rls__List] :=
 {id -> #[[1, 1]], tag -> Union @@ #[[All, 2]]} & /@
  GatherBy[{id, tag} /. Join[rls], First]

combine[playerId, games, list1, list2]
{{playerId -> 1, games -> {{11, "info"}, {12, "info"}, {13, "info"}}},
 {playerId -> 2, games -> {{21, "info"}}},
 {playerId -> 3, games -> {{31, "info"}}}}

Or, if you prefer, using Sow and Reap:

combine2[id_, tag_, rls__List] :=
  Last @ Reap[Sow @@@ ({tag, id} /. Join[rls]), _, {id -> #, tag -> Union @@ #2} &]

combine2[playerId, games, list1, list2]
{{playerId -> 1, games -> {{11, "info"}, {12, "info"}, {13, "info"}}},
 {playerId -> 2, games -> {{21, "info"}}},
 {playerId -> 3, games -> {{31, "info"}}}}
share|improve this answer
1  
... you took the time to do it properly, though. I confess to being a hardcoding bum. But it is Sunday and the sun is a-shining :D –  Yves Klett Mar 16 at 14:51
    
@Yves Then get off the computer and go play! :-) –  Mr.Wizard Mar 16 at 14:51
1  
Beep beep zoom! –  Yves Klett Mar 16 at 14:53

Abstaining from using ReplaceAll:

{DeleteDuplicates[#[[1]]][[1]], 
   games -> 
    DeleteDuplicates@Flatten[#[[2, All, 2]], 1]} & /@ (Transpose /@ 
   GatherBy[Join[list1, list2], First])

Result:

(*{{playerId -> 1, games -> {{11, "info"}, {12, "info"}, {13, "info"}}},
   {playerId -> 2, games -> {{21, "info"}}},
   {playerId -> 3, games -> {{31, "info"}}}}*)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.