5

Say you have a List of objects. The User uses mostly all objects when he is working. How can you order the list of objects, so that the list adapts to the order, the users uses mostly? What algorithm can you use for that?

EDIT: Many answers suggested counting the number of times an object was used. This does not work, because all objects are used the same amount, just in different orders.

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • That's really broad. Do you have an idea of what specifically you are looking for? Are you intending to ordering by preferred columns? Or use more of a heuristic approach? – Kendall Frey Jun 28 '12 at 12:57
  • Are these objects of same type? You could probably create a base class that all object types will inherit and that will expose (int)UsageCount property. You can then incrememnt this on each use and order by it – Dimitri Jun 28 '12 at 12:58
  • The user uses all Objects everytime. So Usedcount will be the same for all Objects. Simply the order in which the user uses the objects varies from user to user.. and so i need an algorithmic approch for ordering the list. Isn't there any approach using Decision Trees? – Tombi Unnso Jun 28 '12 at 13:03
  • 2
    If it is truely a question of user preferences, maybe you'd be better off by giving the user the option to order the list themselves instead of trying to guess what he would prefer. – Falanwe Jun 28 '12 at 13:08

10 Answers10

2

Inside your object, keep a usedCount. Whenever the object is used, increase this count. Then you can simply do this:

objects.OrderByDescending(o => o.UsedCount);
Erix
  • 7,059
  • 2
  • 35
  • 61
1

I would keep a running count of how many times the object was used, and in what order it was used.

So if object X was used 3rd, average it with the running count and use the result as it's position in the list.

For example:

Item       Uses     Order of Use
---------------------------------------
Object X   10       1,2,3,1,2,1,3,1,2,2 (18)
Object Y   10       3,1,2,3,3,3,1,3,3,1 (23)
Object Z   10       2,3,1,2,1,2,2,2,2,3 (20)

Uses would be how many times the user used the object, the order of use would be a list (or sum) of where the item is used in the order.

Using a list of the each order individually could have some performance issues, so you may just want to keep a sum of the positions. If you keep a sum, just add the order to that sum every time the object is used.

To calculate the position, you would then just use the sum of the positions, divided by the number of uses and you'd have your average. All you would have to do at that point is order the list by the average.

In the example above, you'd get the following averages (and order):

Object X   1.8
Object Z   2.0
Object Y   2.3
jsmith
  • 976
  • 8
  • 19
0

Add a list of datetimes of when a user accesses an object. Each time a user uses an object, add a datetime.

Now just count the number of datetime entries in your list that are w (now - x days) and sort by that. You can delete the datetimes that are > (now - x days).

It's possible that a user uses different items in a month, this will reflect those changes.

Carra
  • 17,808
  • 7
  • 62
  • 75
  • This is not what he wants. If i use object A 100 times and then use object B once, the B object will be on top, whereas he wants object A to be on top since its the most used one – Dimitri Jun 28 '12 at 13:00
  • Fair enough, changed my answer. – Carra Jun 28 '12 at 13:02
  • I don't want to be annoying but why not just add int field that will be incremented each time an object is used. then order by the field :) – Dimitri Jun 28 '12 at 13:04
  • Simple, the objects I'm currently using are different than those I will use in a year. I'm thinking of my objects as programs that I use. Depending on what you want to do, keeping a list can be enough. – Carra Jun 28 '12 at 13:05
  • Yeah but he's not interested in when object was used, but how many times. – Dimitri Jun 28 '12 at 13:06
0

You can add a number_of_views field to your object class, ++ it every time the object's used and sort list by that field. And you should make this field=0 to all objects when number_of_views at all objects is the same but isn't 0.

Feanor
  • 3,568
  • 5
  • 29
  • 49
0

I would also use a counter for each object to monitor its use, but instead of reordering the whole list after each use, I would recommend to just sort the list "locally". Like in a bubble sort, I would just compare the object whose counter was just increased with the upper object, and swap them if needed. If swapped, I would then compare the object and its new upper object and so on.

However, it is not very different from the previous methods if the sort is properly implemented.

Pixou
  • 1,719
  • 13
  • 23
0

If your User class looks like so:

class User  
{  
    Collection<Algo> algosUsed = new List<Algo>();     //Won't compile, used for explanation
    ...
}  

And your Algo class looks like so:

class Algo  
{  
    int usedCount;  
...  
}  

You should be able to bind specific instances of the Algo object to the User object that allow for the recording of how often it is used. At the most basic level you would serialize the information to a file or a stream. Most likely you want a database to keep track of what is being used. Then when you grab your User and invoke a sort function you order the algos param of User by the usedCount param of Algo

Woot4Moo
  • 23,987
  • 16
  • 94
  • 151
  • The Problem is that all objects are used to an equal extend so the usedCount for everyobject is the same. just the order of usage varies... – Tombi Unnso Jun 28 '12 at 13:12
  • @TombiUnnso I would recommend you rethink the design of the application. – Woot4Moo Jun 28 '12 at 13:14
0

EDIT: ADDED A Order Preferrence!!! look in CODE

I dont like the Last used method as Carra said because it inflict many sort changes which is confusing.

the count_accessed field is much better, though i think it should be levelled to
how many times the user accessed this item in the last XX minutes/hours/days Etc...

the best Datastructure for that is surely

    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;
        }
    }

Hope this helps... it is almost always O(1) BTW...
reminds me somewhat of the Sleep mechanism of Operating Systems

Tomer W
  • 3,395
  • 2
  • 29
  • 44
  • Say a user works a year with the list. The list should then be ordered by the probability of different possibilities from the whole training examples... – Tombi Unnso Jun 28 '12 at 13:18
  • Every time you want to push an item up, you can call the Access_Detected() this will increase the count of Linked list => the better probability the item is first... but what i tried to achieve is that items that been very active "Long time" ago will be "obsolete" compared to current items. – Tomer W Jun 28 '12 at 13:45
  • Node about Edit... the Lower Priority is, the more useful the object – Tomer W Jun 28 '12 at 14:00
0

Sounds like you want a cache. I spose you could look at the algorithms a cache uses and then take out the whole business about context switching...there is an algorithm called "clock sweep"... but meh that might all be too complex for what you are looking for. To go the lazy way I'd say just make a hash of "used thing":num_of_uses or, in your class, have a var you ++ each time the object is used.

Every once and a while sort the hash by num_of_uses or the objects by the value of their ++'d variable.

PinkElephantsOnParade
  • 6,452
  • 12
  • 53
  • 91
0

From https://stackoverflow.com/a/2619065/1429439 :

maybe use OrderedMultiDictionary with the usedCount as the keys and the object as the value.

Community
  • 1
  • 1
C.M.
  • 1,474
  • 13
  • 16
0

When a user interacts with an object, save the ID of the previous object acted upon on that second object so that you always have a pointer to the object used before any given object.

Additionally, store the ID of the most frequently first used object so you know where to start.

When you are building your list of objects to display, you start with the one you've stored as the most frequently first-used object then search for the object that has the first-used object's ID stored on it to display next.

Dylan
  • 151
  • 2
  • 7