假设您有一个对象列表。用户在工作时主要使用所有对象。您如何对对象列表进行排序,以使列表适应用户最常使用的顺序?您可以为此使用什么算法?
编辑:许多答案建议计算使用对象的次数。这不起作用,因为所有对象的使用量都相同,只是顺序不同。
假设您有一个对象列表。用户在工作时主要使用所有对象。您如何对对象列表进行排序,以使列表适应用户最常使用的顺序?您可以为此使用什么算法?
编辑:许多答案建议计算使用对象的次数。这不起作用,因为所有对象的使用量都相同,只是顺序不同。
在您的对象内部,保留一个 usedCount。每当使用对象时,增加此计数。然后你可以简单地这样做:
objects.OrderByDescending(o => o.UsedCount);
我会不断统计该对象被使用的次数,以及使用的顺序。
因此,如果对象 X 被第三次使用,则将其与运行计数进行平均,并将结果用作它在列表中的位置。
例如:
项目使用使用顺序 -------------------------------------- 对象 X 10 1,2,3,1,2,1,3,1,2,2 (18) 对象 Y 10 3,1,2,3,3,3,1,3,3,1 (23) 对象 Z 10 2,3,1,2,1,2,2,2,2,3 (20)
使用将是用户使用该对象的次数,使用顺序将是该项目在该顺序中的使用位置的列表(或总和)。
单独使用每个订单的列表可能会出现一些性能问题,因此您可能只想保留头寸的总和。如果您保留一个总和,只需在每次使用对象时将顺序添加到该总和。
要计算位置,您只需使用位置的总和除以使用次数即可得到平均值。那时您所要做的就是按平均值对列表进行排序。
在上面的示例中,您将获得以下平均值(和顺序):
对象 X 1.8 对象 Z 2.0 对象 Y 2.3
您可以将 number_of_views 字段添加到您的对象类,每次使用对象时 ++ 它并按该字段对列表进行排序。当所有对象的 number_of_views 相同但不为 0 时,您应该为所有对象设置此字段 = 0。
来自https://stackoverflow.com/a/2619065/1429439:
可能使用 OrderedMultiDictionary,其中 usedCount 作为键,对象作为值。
我还会为每个对象使用一个计数器来监视它的使用,但不是在每次使用后重新排序整个列表,我建议只对列表进行“本地”排序。就像在冒泡排序中一样,我只会将计数器刚刚增加的对象与上面的对象进行比较,并在需要时交换它们。如果交换,我会比较该对象和它的新上层对象,依此类推。
但是,如果正确实现了排序,它与以前的方法并没有太大的不同。
当用户与对象交互时,保存对第二个对象执行的前一个对象的 ID,以便您始终拥有指向在任何给定对象之前使用的对象的指针。
此外,存储最常用的第一个对象的 ID,以便您知道从哪里开始。
当您构建要显示的对象列表时,您从存储为最常用的第一次使用的对象开始,然后搜索存储了第一次使用的对象 ID 的对象以在下一个显示。
编辑:添加了订单偏好!!!看代码
我不喜欢 Carra 所说的 Last used 方法,因为它会造成许多令人困惑的排序变化。
count_accessed 字段要好得多,尽管我认为应该将其调整为
用户在过去 XX 分钟/小时/天等内访问该项目的次数等...
最好的数据结构肯定是
static TimeSpan TIME_TO_LIVE;
static int userOrderFactor = 0;
LinkedList<KeyValuePair<DateTime, int>> myAccessList = new LinkedList<KeyValuePair<DateTime, int>>();
private void Access_Detected()
{
userOrderFactor++;
myAccessList.AddLast(new KeyValuePair<DateTime, int>(DateTime.Now, userOrderFactor));
myPriority += userOrderFactor; // take total count differential, so we dont waste time summing the list
}
private int myPriority = 0;
public int MyPriority
{
get
{
DateTime expiry = DateTime.Now.Subtract(TIME_TO_LIVE);
while (myAccessList.First.Value.Key < expiry)
{
myPriority += myAccessList.First.Value.Value; // take care of the Total Count
myAccessList.RemoveFirst();
}
return myPriority;
}
}
希望这会有所帮助......它几乎总是 O(1) BTW......
让我想起了操作系统的睡眠机制
如果您的 User 类看起来像这样:
class User
{
Collection<Algo> algosUsed = new List<Algo>(); //Won't compile, used for explanation
...
}
你的算法类看起来像这样:
class Algo
{
int usedCount;
...
}
您应该能够将Algo
对象的特定实例绑定到User
允许记录使用频率的对象。在最基本的层面上,您会将信息序列化为文件或流。您很可能想要一个数据库来跟踪正在使用的内容。然后,当你抓住你的User
并调用一个sort
函数时,你按参数algos
排序参数User
usedCount
Algo
听起来你想要一个缓存。我想你可以看看缓存使用的算法,然后拿出关于上下文切换的整个业务......有一种叫做“时钟扫描”的算法......但是对于你正在寻找的东西来说,这可能都太复杂了. 采取懒惰的方式,我想说只是做一个“用过的东西”的哈希:num_of_uses 或者,在你的类中,每次使用对象时都有一个 var you ++。
每隔一段时间,按 num_of_uses 或对象按 ++'d 变量的值对散列进行排序。
添加用户访问对象的日期时间列表。每次用户使用对象时,添加一个日期时间。
现在只需计算列表中 w (现在 - x 天)的日期时间条目数并按此排序。您可以删除 >(现在 - x 天)的日期时间。
用户可能在一个月内使用不同的项目,这将反映这些变化。