我有一个包含KeyValuePair<int, double>
的列表,按双精度排序,其中int
代表 ID ,double
代表该ID的分数。我想创建一个算法,它给出了ID的前k个,其中ID的总和最大化。现在,我知道如何做到这一点,但我不知道如何在c#中实现它。
因此,我们的想法是获取每个列表的第一个元素并计算阈值&#39;,该行的得分总和,即总和的最大值。然后我们查找该行中ID的所有分数总和,并将其放入缓冲区。然后我们移动到下一行并计算阈值和分数,如果缓冲区中的一个分数高于当前阈值,我们知道它应该在top-k中并将其放在那里然后继续我们有k值。我希望有人能指出我正确的方向。
一些示例数据: 列表中有两个列表如下:
{(1, 25), (2, 23), (3, 19), (4, 10), (5, 3)},
{(2, 24), (3, 20), (1, 15), (5, 10), (4, 3)}
在第一轮之后,我们的阈值为25+24 = 49
,缓冲区由(1, 40)
和(2, 47)
组成。我们移动到下一行并找到值(2, 23)
和(3, 20)
,因此阈值为43,我们将(3, 39)
添加到缓冲区。我们在缓冲区中看到ID为2的元组的分数高于阈值,因此我们将其添加到Top-k。
这些列表最多包含100000 KeyValuePairs
,而且只需要处理一些KeyValuePairs
来查找top-k,而不是只计算每个元组的得分并取得前k个
答案 0 :(得分:0)
如果您的意思是按Key
总计一个键值对列表,其中得分为Value
,那么您可以非常简单地使用Linq,例如获得前2名玩家得分:
var playerScores = new List<KeyValuePair<int, double>>() {
new KeyValuePair<int, double>(1, 1.0),
new KeyValuePair<int, double>(2, 20.0),
new KeyValuePair<int, double>(3, 10.8),
new KeyValuePair<int, double>(1, 15.2),
new KeyValuePair<int, double>(2, 10.2),
new KeyValuePair<int, double>(3, 8.4),
new KeyValuePair<int, double>(1, 3),
new KeyValuePair<int, double>(2, 6.6),
new KeyValuePair<int, double>(3, 9.2),
};
var totalScores = playerScores
.GroupBy(a => a.Key)
.Select(g => new { id = g.Key, total = g.Sum(gk => gk.Value) })
.OrderByDescending(x => x.total);
foreach (var player in totalScores.Take(2)) // find the top 2 scores
{
Console.WriteLine($"player {player.id} scores {player.total}");
}
输出:
player 2 scores 36.8
player 3 scores 28.4