对一组对象进行排序的算法

5
假设您有一个对象列表。用户在工作时使用大部分对象。如何对对象列表进行排序,以便列表适应用户最常使用的顺序?您可以使用什么算法?
编辑:许多答案建议计算使用对象的次数。这种方法不起作用,因为所有对象都被使用相同的次数,只是使用的顺序不同。

那个问题太泛泛了。你有没有具体想法?你打算按喜好的列排序吗?还是采用更加启发式的方法? - Kendall Frey
这些对象是同一类型吗?您可以创建一个所有对象类型都将继承并公开(int)UsageCount属性的基类。然后,您可以在每次使用时增加它,并按其排序。 - Dimitri
用户每次都使用所有对象。因此,所有对象的 Usedcount 都相同。仅用户使用对象的顺序因人而异。因此,我需要一种算法方法来排序列表。是否有使用决策树的方法? - Tombi Unnso
2
如果这确实是用户偏好的问题,也许你最好让用户自己选择列表的顺序,而不是试图猜测他会喜欢什么。 - Falanwe
10个回答

2
在你的对象内部,保留一个usedCount。每当对象被使用时,增加这个计数。 然后你可以简单地这样做:
objects.OrderByDescending(o => o.UsedCount);

1

我会保持一个运行计数器,记录对象被使用的次数以及使用顺序。

因此,如果对象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

0
如果您的用户类看起来像这样:
class User  
{  
    Collection<Algo> algosUsed = new List<Algo>();     //Won't compile, used for explanation
    ...
}  

你的算法类看起来像这样:

class Algo  
{  
    int usedCount;  
...  
}  

您应该能够将Algo对象的特定实例绑定到User对象,以允许记录其使用频率。在最基本的级别上,您将把信息序列化到文件或流中。最可能的是,您需要一个数据库来跟踪正在使用的内容。然后,当您获取您的User并调用sort函数时,您将通过AlgousedCount参数对Useralgos参数进行排序。


问题在于所有对象被同等使用,因此每个对象的usedCount相同,只是使用顺序不同... - Tombi Unnso
@TombiUnnso 我建议你重新考虑应用程序的设计。 - Woot4Moo

0

编辑:添加了一个排序偏好!请查看代码

我不喜欢上次使用的方法,因为它会导致许多排序更改,这很令人困惑。

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)的... 让我有些想起操作系统的睡眠机制。

假设用户使用列表工作了一年。然后,该列表应按照整个训练示例中不同可能性的概率进行排序... - Tombi Unnso
每次您想将一个项目推上去时,可以调用Access_Detected()函数,这将增加链表的计数=>更好的概率是该项目排在第一位...但我试图实现的是,与当前项目相比,长时间以前非常活跃的项目将变得“过时”。 - Tomer W
节点关于编辑...优先级越低,对象越有用。 - Tomer W

0

添加一个日期时间列表,记录用户访问对象的时间。每当用户使用一个对象时,都要添加一个日期时间。

现在只需计算列表中 w 天前(即当前时间减去 x 天)的日期时间条目数量,并按此进行排序。您可以删除大于 (now - x 天) 的日期时间。

可能会出现用户在一个月内使用不同的项目,这将反映这些更改。


这不是他想要的。如果我使用对象A 100次,然后使用对象B一次,那么B对象将处于顶部,而他希望对象A处于顶部,因为它是最常用的。 - Dimitri
好的,我改变了我的答案。 - Carra
我不想让人感到烦恼,但为什么不添加一个整数字段,每次使用对象时都会递增该字段,然后按该字段排序 :) - Dimitri
简单来说,我现在使用的对象与一年后将要使用的对象不同。我把我的对象看作是我使用的程序。根据你想要做什么,保持一个列表可能就足够了。 - Carra
是的,但他不关心对象何时被使用,而在乎被使用了多少次。 - Dimitri

0
你可以在对象类中添加一个 number_of_views 字段,每次使用该对象时将其 ++,并按照该字段对列表进行排序。当所有对象的 number_of_views 相同时但不为 0 时,应将此字段设置为所有对象的值为 0。

0
我也会为每个对象使用一个计数器来监视其使用情况,但我建议在每次使用后不要重新排序整个列表,而是只在本地对列表进行排序。 就像冒泡排序一样,我只需将刚刚增加计数器的对象与上面的对象进行比较,如果需要,就交换它们。如果交换了,我就会比较对象及其新的上面的对象等等。
然而,如果排序得到适当的实现,那么它与以前的方法并没有太大区别。

0

听起来你想要一个缓存。我猜你可以看一下缓存使用的算法,然后去掉关于上下文切换的整个业务...有一个叫做“时钟扫描”的算法...但是这可能对你所寻找的东西来说太复杂了。为了走捷径,我建议只需将“已使用的物品”:使用次数制作成哈希表,或者在你的类中,每次使用对象时都增加一个变量。

每隔一段时间按num_of_uses对哈希表进行排序,或按其++'d变量的值对对象进行排序。


0

0

当用户与一个对象交互时,保存上一个操作对象的ID到该第二个对象上,以便您始终有指向任何给定对象之前使用的对象的指针。

此外,存储最常用的第一个使用的对象的ID,以便您知道从哪里开始。

在构建要显示的对象列表时,您从已存储为最常用的第一个使用的对象开始,然后搜索具有存储在其上的第一个使用的对象ID的对象以显示下一个对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接