8

I have class Reward which i keep user money per game. I have two list somehow I need to concate. I write sample lists and desired result below.

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

Result List should be

User Money
1    25
2    45
3    30
4    35

I try

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

but how?

6 Answers 6

6

You were on the right track with GroupBy, this should do the job:

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: Same thing with lambda expression:

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)
    });
Sign up to request clarification or add additional context in comments.

Comments

0

This isn't very pretty, but it works.

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

Comments

0

With .GroupBy, you get a list of IGrouping, so the select is like so:

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

Comments

0

I imagine an answer close to what you are looking for looks like this:

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

As far as which game to use, you might consider an anonymous select (i.e.

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

This would give you an anonymous type that holds the information you wish to use. If you are going to pass it out of the method, however, it's best practice to give it a type, or just understand that game 0 is your superset of all games.

Comments

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

Comments

0

Please change the line:

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

to

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.