我有一些客户参考,每个参考都有一些属性:
现在,我想选择要显示在主页上的部分参考。引用应该随机选择,以便每次有人访问我的主页时它们都不同。同时,我希望所选参考文献满足某些条件:
如何创建这样的选择算法?
| Column | Type | Key type |
|------------------|--------|-------------|
| ReferenceId | int | Primary key |
| AuthorName | string | |
| OrganisationName | string | |
| Content | string | |
| AddedDate | date | |
| SolutionId | int | Foreign key |
| IndustryId | int | Foreign key |
| BrandIsStrong | bool | |
| RegionId | int | Foreign key |
一般思路:为参考分配权重,并根据参考权重组合选择参考。例如这样的
DateWeight
。参考值越大,权重越低。SolutionWeight
。对于每次迭代,减少分配的权重。最后,每个解决方案中都有一个引用,其中SolutionWeight
高,SolutionWeight
稍低,依此类推。如果现在通过减小SolutionWeight
查看所有引用,解决方案的差异会很大。IndustryWeight
而不是SolutionWeight
。BrandWeight
而不是SolutionWeight
。RegionWeight
而不是SolutionWeight
。n
个引用以显示在主页上。例如,这可以通过以下方式完成:
一般思想:遍历每个约束,一次选择一个参考。
Unselected
为尚未选择的参考集。Unselected
中的最新参考文献。Unselected
中选择一个属于该解决方案的随机引用。Unselected
中选择一个属于该行业的随机引用。Unselected
中选择一个属于该区域的随机参考。n
个引用为止。此解决方案的缺点是,如果约束之一包含许多选项(例如,不同行业的数量大于n
)。然后,该过程将在甚至完成一次迭代之前停止。
一般思想:对于每个选定的参照,请减少分配给与选定参照具有相同属性的参照的权重。
n
个引用为止。答案 0 :(得分:1)
我认为这主要取决于如何量化可接受的解决方案以及如何定义约束There should be a variety in [...]
。您还必须决定在数据高度相关的情况下该怎么做:例如,如果大多数“强品牌”参考来自一个“行业”,那么由于您希望代表许多行业,因此只有一小部分“品牌”元素。在这种情况下,您将无法同时拥有两者。
让我们假设您需要在页面上显示n
个项目。这是一个外部约束,可能由包含项目列表的Web元素的大小定义;其余约束由您选择。
跳转到底部的 tl; dr 部分以跳过详细信息。
您可以简单地随机选择n
个引用,然后由Universe决定将哪些项添加到您的页面。如果您的数据或多或少均匀地分布在各个列中,并且如果n
“足够大”,则大多数时候您将获得足够的数据。如果需要快速实现,这也使您的代码很容易维护/升级,因此可以在有更好算法的情况下稍后再使用。
现在这不能解决
最近添加的参考文献被选中的可能性更高
部分,所以我们可以做得更好
这是第一个解决方案的略微修改版本。在这一步中,您从最新的“ ReferenceId”开始,并按照“ ReferenceId”的降序,沿数据集进行迭代。每个项目都有被选择的概率p
,选择的可能性是使n
元素通常位于数据集的N
最近的元素内。如果您在选择n
元素之前到达底部,则只需从顶部重新开始(或增加p
)。
在Java中,它看起来像:
for (Object item : items) {
if (random.nextDouble() < p) {
result.add(item);
}
if (result.size() == n) {
break;
}
}
但是,如果您的数据不是不均匀分布(可能是这种情况,因为您是在问这个问题),那么您就不能仅依靠随机性来生成项目集。在继续进行解决方案3之前,请检查此解决方案是否对您有用。如果没有,
您现在要做的是定义一组大小n
以满足全局数据集要求的含义。
您必须知道,由于要调整最终组合中每个被选中项目的几率,因此您可能无法真正拥有
每次有人访问我的主页时,它们都是不同的
要真正确定这一点,请想象一个示例,其中“区域”之一仅由整个数据集中的一项表示:由于您要强制采用多样性,因此它很可能始终位于最终选择的子集中。还有一个事实是,由于您对最近添加的引用具有特权,因此您的数据分布将更紧密地反映最新条目的数据分布。
因此,现在您不必总是具有 true 随机性和统一表示,就可以放心了,让我们制定约束条件。列的约束可以采用“我希望在最终子集中与该列至少具有n/10
个不同的元素”的形式。您可以使用函数(S, n, k) -> {true, false}
将约束的状态评估为“满意”或“不满意”,其中:
S
是当前所选项目集n
是所选项目的所需大小k
是该列的基数说“给定当前的元素子集,此约束是否得到满足?”。您还可以评估元素是否有助于满足约束条件,例如:“给定元素的当前子集,如果添加此项,我们是否更接近满足该约束条件?”。
就像上面的解决方案2一样进行迭代,并保留每个元素的随机性,还添加了约束Set
约束的检查。满足约束后,将其从约束集中删除。
没有实现细节,您将得到类似的信息:
for (Object item : items) {
// every item still has some probability of being chosen or not
if (random.nextDouble() < p && helpsSatsfyAtLeastOne(remainingConstraints, item, result, n)) {
result.add(item);
}
for (/* Appropriate data structure */ constraint : remainingConstraints) {
if (constraint.isSatisfied(result, n)) {
constraints.remove(constraint);
}
}
if (result.size() == n) {
break;
}
}
System.out.println("Unsatisfied constraints: " + remainingConstraints);
您可以实施helpsSatsfyAtLeastOne(...)
来强制执行约束的顺序,以满足需要优先排序的约束,或者只是使它以不特定的顺序遍历约束。
这是一种贪婪的方法,您不能保证最终结果将是100%完美的。如果最后仍然不能满足某些约束条件,请尝试在这些约束条件中强制执行优先级。
这种方法很简单,大多数情况下应该可以给您足够好的结果。如果不是这样,并且您的数据集如此具体,以至于您需要更精确的解决方案,那么还有更多工作要做。但我认为情况并非如此,因为您只想要网页上一组不错的多样化元素。
p
可能性
someColumn
的数量?)。如果是这样,请将其添加到
结果。someColumn
的 个?
设置?”)。删除这些约束。