2011-11-02 10 views
5

Ho un premio di classe che tengo il denaro dell'utente per gioco. Ho due elenchi in qualche modo che devo conciliare. Scrivo elenchi di campioni e il risultato desiderato di seguito.Unisci due elenchi in base alla chiave C#

public class Reward 
{ 
    public int Game { get; set; } 
    public int User { get; set; } 
    public int Money { get; set; } 

    public Reward Merge(Reward p) 
    { 
     return new Reward { Game = this.Game, User = this.User, Money = this.Money + p.Money}; 
    } 
} 

    IList<Reward> list1 = new List<Reward>(); 
    list1.Add(new Reward {Game = 1, User = 1, Money = 10}); 
    list1.Add(new Reward { Game = 1, User = 2, Money = 20 }); 
    list1.Add(new Reward { Game = 1, User = 3, Money = 30 }); 


    IList<Reward> list2 = new List<Reward>(); 
    list2.Add(new Reward { Game = 2, User = 1, Money = 15 }); 
    list2.Add(new Reward { Game = 2, User = 2, Money = 25 }); 
    list2.Add(new Reward { Game = 2, User = 4, Money = 35 }); 

elenco dei risultati dovrebbe essere

User Money 
1 25 
2 45 
3 30 
4 35 

provo

IList<Reward> listConcat = list1.Concat(list2) 
       .GroupBy(u=> u.User) 
       .Select(???) 
       .ToList(); 

ma come?

risposta

4

Tu eri sulla strada giusta con GroupBy, questo dovrebbe fare il lavoro:

IEnumerable<Reward> result = 
    from r in list1.Concat(list2) 
    group r by r.User into groupedRewards 
    select new Reward 
    { 
     Game = 0, //what game to use? 
     User = groupedRewards.Key, 
     Money = groupedRewards.Sum(r => r.Money) 
    }; 

EDIT: Stessa cosa con l'espressione lambda:

IEnumerable<Reward> result = list1.Concat(list2) 
    .GroupBy(u => u.User) 
    .Select(g => new Reward 
    { 
     Game = 0, //what game to use? 
     User = g.Key, 
     Money = g.Sum(r => r.Money) 
    }); 
+0

+1 solo per renderlo più leggibile rispetto al resto –

0

Si prega di modificare la linea:

return new Reward { Game = this.Game, User = this.User, Money = this.Money + p.User 

a

return new Reward { Game = this.Game, User = this.User, Money = this.Money + p.Money 
0

Questo non è molto bello, ma funziona.

var listConcat = list1.Concat(list2) 
       .GroupBy(u=> u.User) 
       .Select(rewards => new Reward { 
               User = rewards.Key, 
               Money = rewards.Select(reward => reward.Money).Sum() 
               } 
         ) 
       .ToList(); 
0

Con .GroupBy, si ottiene un elenco di IGrouping, quindi la selezione è in questo modo:

IEnumerable<Reward> listConcat = list1.Concat(list2) 
           .GroupBy(x => x.User) 
           .Select(x => new Reward { User= x.Key, Money=x.Sum(y => y.Money) }); 
0

immagino una risposta vicino a quello che state cercando si presenta così:

var catList = list1.Concat(list2) 
        .GroupBy (x => x.User) 
        .Select (y => new Reward{Game = 0, Money = y.Sum (z => z.Money), 
           User = y.Key}) 
        .ToList(); 

per quanto riguarda quale gioco da usare, si potrebbe prendere in considerazione un selezionare anonimo (cioè

.Select(new {Money = y.Sum (z => z.Money), User = y.Key}) 

Questo ti darebbe un tipo anonimo che contiene le informazioni che desideri utilizzare. Se hai intenzione di passare fuori dal metodo, tuttavia, è meglio dargli un tipo, o semplicemente capire che il gioco 0 è il tuo superset di tutti i giochi.

0
IList<Reward> listConcat = list1.Concat(list2) 
       .GroupBy(person => person.User) 
       .Select(group => group.Aggregate((rewardone, rewardtwo) => rewardone.Merge(rewardtwo))) 
       .ToList();