3

I need a dictionary (or any other collection) that stays always sorted by value and can be indexed by key. My purpose is to implement a cache where objects have a unique key and a metric associated to them. When a cache replacement has to be done objects with the least metric are removed. It needs to be as fast as possible, so to make a full ordering each time a replacement is done is not a good option. Any ideas? Thx

slugster
  • 47,434
  • 13
  • 92
  • 138
Ricardo
  • 31
  • 1
  • would a `KeyedCollection` suit your needs? http://msdn.microsoft.com/en-us/library/ms132438.aspx is the key part of the item? – Russ Cam Aug 17 '11 at 08:06
  • 1
    How do you sort a C# dictionary by value - http://stackoverflow.com/questions/289/how-do-you-sort-a-c-dictionary-by-value – sll Aug 17 '11 at 08:07
  • possible duplicate of [.NET SortedDictionary But Sorted By Values](http://stackoverflow.com/questions/2619051/net-sorteddictionary-but-sorted-by-values) – nawfal Jun 05 '14 at 19:50

5 Answers5

3

Something like this should work fine (not tested very much):

http://pastebin.com/eYeE33F5

digEmAll
  • 53,114
  • 9
  • 109
  • 131
0

It seams that priority queue is what you are looking for. There are good implementations of this class using binary heap. Example : http://www.codeproject.com/Articles/126751/Priority-queue-in-Csharp-with-help-of-heap-data-st.aspx

alexm
  • 6,118
  • 17
  • 23
0

Why don't you just keep the regular Dictionary. Now, whenever you need to do that cache replacement, that's the moment you select the element with the "minimum" value and replace it.

Edit - here is how you get the KeyPair with the minimum value. Just use the Key and Value properties after that:

var minValuePair = myDictionary.OrderBy(p => p .Value).First();
Vladimir
  • 3,329
  • 16
  • 18
  • Thanks for your answer. Now i'm doing something like that: `myDictionary.Min(x => x.Value)` but it is very slow. I would like that the dictionary would be always sorted, that is, when a new object is inserted into the dictionary it should be placed in the correct position for its metric. – Ricardo Aug 17 '11 at 08:51
  • @Ricardo Yes, actually I offered an alternative solution. You said that you need the Dictionary sorted for the purpose of removing the minimum value pair when you need to update the cache. That would mean you won't need the Dictionary sorted at all times, you just need the minimum value sometimes. – Vladimir Aug 17 '11 at 08:54
0

You can combine any kind of fast priority queue (look here: Priority queue in .Net) with a standard Dictionary to a new collection. When inserting a new element, insert a reference to the element into both containers. When looking for an element by "key", use the dictionary. When you are going to delete the element with the lowest "metric", use the priority queue to find it, get the key from the element itself, then it is easy to delete the element references from both containers.

Community
  • 1
  • 1
Doc Brown
  • 18,656
  • 6
  • 48
  • 86
  • Thx @Doc, this is a good idea. However, when a user requests an object that it is already stored in the cache it must be updated, so its metric changes and the order in the queue should also be updated. For example, if a LFU (Least Frequently Used) strategy is used, each time an object is requested its frequency counter, which is used as the metric, is incremented by one. – Ricardo Aug 18 '11 at 07:40
  • @Ricardo: use the "C5 Generic Collection Library" (http://www.itu.dk/research/c5/) for your priority queue, it has operations for deleting elements somewhere "in the middle" of the queue, which gives you the ability of removing and re-inserting elements when their metrics changes. To make this work, you will have to store IPriorityQueueHandle elements in your dictionary instead of the elements itself, but that should not become too complicated. – Doc Brown Aug 18 '11 at 09:14
0

You want a dictionary that is sorted by Value but also has indexing by Key. You can't have your data arranged in two ways at once, so you will have to have two collections, your base key-value dictionary, and a reverse lookup dictionary. Your first one is a standard dictionary, your second one is a SortedDictionary with the same data and the keys and values swapped. You will have to keep the two in sync.

You could also write your own Dictionary implementation to encapsulate these two collections into one.

Tim Rogers
  • 19,990
  • 6
  • 47
  • 66