如何使用LINQ进行分组并选择顶部记录?

问题描述 投票:0回答:1

我正在努力获取一个 linq 语句,该语句为每个具有最大计数的玩家提供一条记录。

我的目标是显示 2 条记录: |玩家|标签 |计数 | | ------ | --- | -----| |玩家1 |橙色| 2 | |玩家2 |苹果| 1 |

我有一个查询 1,它似乎使标签变平。 然后通过查询 2,我为玩家和标签生成分组计数。

有没有办法只为每个玩家选择最上面的记录?

void Main()
{
    Player p1 = new Player { Name = "Player1" };
    Player p2 = new Player { Name = "Player2" };
    List<PlayerAnswerRecord> UsedWords = new List<PlayerAnswerRecord>();
    UsedWords.Insert(0, new PlayerAnswerRecord { Word = new DictionaryEntry{ Word = "fruit", Tags = new List<string>{"apple", "orange"} }, Player = p1, Score = 10, RecordType = AnserRecordType.Valid });
    UsedWords.Insert(0, new PlayerAnswerRecord { Word = new DictionaryEntry{ Word = "fruit2", Tags = new List<string>{"pineapple", "orange"} }, Player = p1, Score = 10, RecordType = AnserRecordType.Valid });
    UsedWords.Insert(0, new PlayerAnswerRecord { Word = new DictionaryEntry{ Word = "fruity", Tags = new List<string>{"apple", "orange"} }, Player = p2, Score = 25, RecordType = AnserRecordType.Valid });
    
    foreach(var w in UsedWords)
    {
        //Console.WriteLine(w.Word.Word);
    }
    
    //UsedWords.GroupBy(
    var grouped =
        from entry in UsedWords
        group entry by entry.Player into newGroup
        select newGroup;
    
    //Console.Write(grouped);
    
    var query = UsedWords
        .Select(x=> new {x.Player, x.Word})
        .SelectMany(x=> x.Word.Tags);
        
    var query1 = UsedWords.SelectMany (
      c => c.Word.Tags, 
      (c, o) => 
         new  
         {
            Player = c.Player.Name, 
            Tag = o
         }
   ); 
    //var query2 = query1.GroupBy(x=>x.Name).Select(group => new {Metric = group.Key, Count = group.Count()});  
    var query2 = query1.GroupBy(x=> new {x.Player, x.Tag}).Select(group => new {Player = group.Key.Player, Tag = group.Key.Tag, Count = group.Count()}).OrderByDescending(x=>x.Count);
    //var query2 = query1.GroupBy(x=>x.Name).Select(group => group, (group, o) => new {Metric = group.Key, Count = group.Count()});
    var query3 = query2.Max(x => x.Count);
    Console.Write(query1);
    Console.Write(query2);
    Console.Write(query3);
}

// You can define other methods, fields, classes and namespaces here

public class PlayerAnswerRecord
{
    public Player Player;
    public DictionaryEntry Word;
    public int Score;
    public float ElapsedTime;
    public AnserRecordType RecordType;
}

public enum AnserRecordType
{
    Valid,
    Invalid,
    OutOfTime,
    UsedWord
}

public class DictionaryEntry
{
    public string Word;
    public List<string> Tags;
}

public class Player
{
    public string Name;
}
c# linq linqpad
1个回答
0
投票

将查询分解为多个部分并没有什么问题。 LINQ 使用延迟执行(即查询在声明时不会执行,而是在迭代输出时执行),因此您可以将查询拆分为任意多个步骤,并且不会影响结果或性能。

但是如果您确实想编写一个查询,则可以使用以下内容:

var result =
    from entry in UsedWords
    from tags in entry.Word.Tags
    group tags by entry.Player.Name
    into tagsGroupedByPlayer
    let mostFrequentTag = (from tags in tagsGroupedByPlayer
        group tags by tags
        into tags
        select new { Tag = tags.Key, Count = tags.Count() } into tagAndCount
        orderby tagAndCount.Count 
        select tagAndCount).First()
    select new { Player = tagsGroupedByPlayer.Key, Tag = mostFrequentTag.Tag, Count = mostFrequentTag.Count };

显然,您可以自由修改最后的

select
子句,将结果投影为您想要的任何格式。

© www.soinside.com 2019 - 2024. All rights reserved.