Объединить два списка с на основе ключа c#

#c# #list #merge

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

Список результатов должен быть

 User Money
1    25
2    45
3    30
4    35
  

Я пытаюсь

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

но как?

Ответ №1:

Вы были на правильном пути с GroupBy, это должно выполнить эту работу:

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

РЕДАКТИРОВАТЬ: то же самое с лямбда-выражением:

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

Ответ №2:

Это не очень красиво, но это работает.

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

Ответ №3:

С .GroupBy помощью, вы получаете список IGrouping , поэтому выбор выглядит так:

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

Ответ №4:

Я полагаю, что ответ, близкий к тому, что вы ищете, выглядит следующим образом:

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

Что касается того, какую игру использовать, вы можете рассмотреть анонимный выбор (т. е.

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

Это даст вам анонимный тип, который содержит информацию, которую вы хотите использовать. Однако, если вы собираетесь передать его из метода, лучше всего присвоить ему тип или просто понять, что game 0 — это ваш надмножество всех игр.

Ответ №5:

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

Ответ №6:

Пожалуйста, измените строку:

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

Для

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