进行有效加权排名的算法?

问题描述

我需要一种算法来对 Twitter 帖子进行快速加权排名。

每个帖子都有许多排名分数(例如年龄、作者关注者数量、关键字提及等)。我正在寻找可以根据每个排名分数的权重快速找到前 N 条推文的算法。

现在,用例是这些权重会发生变化,并且每次权重发生变化时重新计算每条推文的排名分数是非常昂贵的。

我将可以访问已排序的推文列表,每个排名得分一个。所以我正在寻找一种算法来有效地搜索这些列表以找到我的前 N ​​个。

解决方法

注意:提供这个答案是因为我们相信知识总是好的(即使它可能被用于邪恶的目的)。如果您能够在没有确保参与者完全了解他们的数据将如何使用并且没有获得每个参与者的明确同意(并且没有“选择加入”,随时选择退出的能力");那么你就是在侵犯人们的隐私,并应该因为你的严重不道德的恶意软件而破产。多家大公司都在作恶,却没有让事情变得更糟,这已经够糟糕了。

假设有一个像 score = a_rank * a_weight + b_rank * b_weight + c_rank * c_weight 这样的公式。

这可以分成几部分,例如:

 a_score = a_rank * a_weight
 b_score = b_rank * b_weight
 c_score = c_rank * c_weight
 score = a_score + b_score + c_score

如果您知道 a_rank 的范围,您可以将条目分类到“a_rank 桶”中。例如,如果您有 100 个桶并且“a_rank”可以是从“a_rank_min”到“a_rank_max”的值;然后“bucket_number = (a_rank - a_rank_min) * 100 / (a_rank_max - a_rank_min)”。

从这里您可以说特定“a_rank 桶”中的所有条目都必须在特定范围内具有“a_score”;并且您可以仅从“bucket_number”计算存储桶中所有条目的最小和最大可能的“a_score”;使用“min_a_score_for_bucket = (bucketNumber * (a_rank_max - a_rank_min) / 100 + a_rank_min) * a_weight”和“max_a_score_for_bucket = ( (bucketNumber+1) * (a_rank_max - a_rank_min) / 100 + a_rank_min) * a_weight - 1”等公式。

下一步是建立一个“目前得分最高的 10 个条目”。通过从最高的“a_rank bucket/s”中选择前 10 个条目并完整计算它们的分数来完成此操作。

一旦完成(并且您知道“迄今为止的第 10 高分”),您可以为每个存储桶计算过滤器。如果您假设存储桶中的所有条目都具有最大可能的 a_rank(仅由存储桶编号确定)和最大可能的 c_rank(由所有 c_rank 值的可能范围确定),那么您可以计算需要的 b_rank 的最小值参赛作品的分数高于“迄今为止的第 10 高分”;同样,如果您假设存储桶中的所有条目都具有最大可能的 a_rank 和最大可能的 b_rank,您可以计算出所需的 c_rank 最小值。然后可以使用“minimum needed b_rank”和“minimum needed c_rank”跳过那些不可能超过“迄今为止第 10 高分”的条目,而无需计算任何这些条目的分数。

当然,每次您找到比“迄今为止第 10 高分”更高的条目时,您都会得到一个新的“迄今为止第 10 高分”,并且必须重新计算“最低需要的 b_rank”和“最低分”桶需要 c_rank”。理想情况下,您应该以“最高 a_rank 存储桶优先”的顺序查看存储桶,因此只会计算当前存储桶的“最低需要 b_rank”和“最低需要 c_rank”

接近开始时(当您查看具有最高 a_rank 值的存储桶时)它可能不会过滤掉许多条目,甚至可能使性能变差(由于重新计算“最少需要的 b_rank”和“所需的最低 c_rank”值)。接近尾声时(当您查看具有最低 a_rank 值的存储桶时),您可以跳过整个存储桶而无需查看其中的任何条目。

注意:

  • 所有的权重都可以在不改变任何桶的情况下改变;但如果“a_rank”对分数的影响最大,则性能会更好。

  • “a_rank”的值范围不应更改(如果更改,您必须重建存储桶);但是“b_rank”和“c_rank”的值范围可以是可变的(每次创建新条目时都会更新)

  • 以“最高 a_rank 优先”的顺序对每个桶进行排序(然后使用“最高 b_rank 优先”作为决胜局等)将有助于在找到 10 个得分最高的条目时提高性能;但它也会在添加条目时增加开销。出于这个原因,在大多数情况下,我可能根本不会理会桶的内容。

  • 如果您可以为“a_rank”的每个可能值设置一个存储桶,那就太好了;因为这提供了排序的几乎所有好处,而没有任何排序开销。如果您无法为“a_rank”的每个可能值设置一个存储区,那么增加存储区的数量有助于提高性能。

  • 理论上;可以有多层“桶”(例如,包含“b_rank 桶”的“a_rank 桶”)。这会显着增加复杂性,并增加内存消耗;但是(尤其是在没有进行排序的情况下)可能会显着提高性能(并且可能会使性能变差)。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...