What's the difference between SortedList and SortedDictionary?
Yes - their performance characteristics differ significantly. It would probably be better to call them SortedList
and SortedTree
as that reflects the implementation more closely.
Look at the MSDN docs for each of them (SortedList
, SortedDictionary
) for details of the performance for different operations in different situtations. Here's a nice summary (from the SortedDictionary
docs):
The
SortedDictionary<TKey, TValue>
generic
class is a binary search tree with
O(log n) retrieval, where n is the
number of elements in the dictionary.
In this, it is similar to the
SortedList<TKey, TValue>
generic
class. The two classes have similar
object models, and both have O(log n)
retrieval. Where the two classes
differ is in memory use and speed of
insertion and removal:
SortedList<TKey, TValue>
uses less
memory thanSortedDictionary<TKey,
.
TValue>
SortedDictionary<TKey, TValue>
has
faster insertion and removal
operations for unsorted data, O(log n)
as opposed to O(n) for
SortedList<TKey, TValue>
.If the list is populated all at once
from sorted data,SortedList<TKey,
is faster than
TValue>
SortedDictionary<TKey, TValue>
.
(SortedList
actually maintains a sorted array, rather than using a tree. It still uses binary search to find elements.)
SortedList, SortedDictionary and Dictionary
When iterating over the elements in either of the two, the elements will be sorted. Not so with
Dictionary<T,V>
.MSDN addresses the difference between
SortedList<T,V>
andSortedDictionary<T,V>
:
The SortedDictionary(TKey, TValue) generic class is a binary search
tree with O(log n) retrieval, where n is the number of elements in
the dictionary. In this respect, it is similar to the SortedList(TKey,
TValue) generic class. The two classes have similar object models, and
both have O(log n) retrieval. Where the two classes differ is in
memory use and speed of insertion and removal:SortedList(TKey, TValue) uses less memory than SortedDictionary(TKey,
TValue).SortedDictionary(TKey, TValue) has faster insertion and removal
operations for unsorted data: O(log n) as opposed to O(n) for
SortedList(TKey, TValue).If the list is populated all at once from sorted data,
SortedList(TKey, TValue) is faster than SortedDictionary(TKey,
TValue).
Why SortedListTKey, TValue doesn't use pointers for the values?
This should not surprise you, it is well documented in the MSDN article for SortedList:
SortedDictionary has faster insertion and removal operations for unsorted data, O(logn) as opposed to O(n) for SortedList.
SortedDictionary uses a red-black tree (i.e. "pointers"), SortedList is an array. You choose between the two based on what you do with the collection. Both are O(logn) for lookup, but if you iterate the collection frequently then you can be ahead with SortedList a great deal. It uses the cpu caches much more effectively. Makes a huge difference on modern machines.
Also do note that the efficiency of adding items to the collections is heavily dependent on how sorted the items are. A SortedDictionary really likes random data, gives it much better odds of not having to re-balance the trees. Having it sorted gives it worst-case O(n) behavior. SortedList really likes sorted items, makes adding O(1).
Can a SortedList/SortedDictionary with a properly implemented comparer be used to guarantee insertion order?
A comparer must obey the law
Compare(a, b) == -Compare(b, a) //assuming only possible values are -1, 0, 1
This is the symmetry property. Your sample code does not obey it. Therefore the BCL collections do not give you any guarantee at all. You have violated the documented contract.
You can't do this.
Instead, you could add a new field to M
where you store the insertion order as an int
. You can then use that field in the comparer.
Dictionary vs SortedList for data storage and processing
Use SortedDictionary<TKey, TValue> Class
.
SortedDictionary<DateTime, Class2> dict = new SortedDictionary<DateTime, Class2>();
Following from the documentation explains well about the difference between using a SortedList
vs SortedDictionary
The
SortedDictionary<TKey, TValue>
generic class is a binary search
tree withO(log n)
retrieval, where n is the number of elements in
the dictionary. In this respect, it is similar to the
SortedList<TKey, TValue>
generic class. The two classes have similar
object models, and both have O(log n) retrieval. Where the two classes
differ is in memory use and speed of insertion and removal:
SortedList<TKey, TValue>
uses less memory thanSortedDictionary<TKey, TValue>
.
SortedDictionary<TKey, TValue>
has faster insertion and removal operations for unsorted data: O(log n) as opposed to
O(n) forSortedList<TKey, TValue>
.If the list is populated all at once from sorted data,
SortedList<TKey, TValue>
is faster thanSortedDictionary<TKey, TValue>
.
For your question:
What's the best practice for creating the list (of Value1)?
List<decimal> list = dict.Values.Select(r=> r.Value1).ToList();
For your comment:
how to form a list consisting of Values1, say, for the last 3 days
List<decimal> listOfValue1 = dict.Where(r=> r.Key >= DateTime.Today.AddDays(-3)
&& r.Key <= DateTime.Today)
.Select(r=> r.Value.Value1)
.ToList();
C#: does SortedListTKey,TValue implement IReadOnlyDictionaryTKey,TValue?
It doesn't say you can't pass them, it just says it doesn't know how. You can manually cast the objects to IReadOnlyCollection.
funcIROCollKvp1((IReadOnlyCollection < KeyValuePair<int, string> > )listkvp);
funcIROCollKvp1((IReadOnlyCollection < KeyValuePair<int, string> > )dict);
Which class type should I use for sorted collection with key updating and value lookup
You could use a List<Character>
, or an array excluding the player's character. You keep the List<Character>
sorted with the highest aggro value at the front. To keep everything sorted every frame you run quicksort first. Once a Character
has a lower aggro value than the player's aggro threshhold you escape out of the method.
If aggro is above the threshold just run the aggro check.
You could extend this to work for multiplayer by having a List<Player>
.
Something like:
void quicksort(List<Enemy> enemies, int first, int last)
{
int left = first;
int right = last;
int pivot = first;
first++;
while (last >= first)
{
if(enemies[first].Aggro >= enemies[pivot].Aggro &&
enemies[last].Aggro < enemies[pivot].Aggro)
swapp(enemies, first, last)
else if(enemies[first].Aggro >= enemies[pivot].Aggro)
last--;
else if(enemies[last].Aggro < colliders[pivot].Aggro)
first++;
else
{
last--;
first++;
}
}
swap(enemies, pivot, last);
pivot = last;
if(pivot > left)
quicksort(enemies, left, pivot);
if(right > pivot + 1)
quicksort(enemies, pivot + 1, right);
}
void swap(List<Enemy> enemies, int left, right)
{
var temp = enemies[right];
enemies[right] = enemies[left];
enemies[left] = temp;
}
void CheckAggro()
{
quicksort(enemies, 0, enemies.Count - 1);
for(int = 0; i < players.Count; i++)
{
for(int j = 0 < enemies.Count; j++)
{
if(players[i].AggroThreshhold < enemies[j].Aggro)
{
break;
}
// Perform what happens when enemy is high on aggro threshold.
}
}
}
If players have different aggro thresholds you could save all of the enemies who have aggro above the minimum to a separate List
, and then do a check against that from the player with the lowest to highest threshold. Just keep the list of players sorted with the lowest aggro threshold first.
Is there a usual style for using C#'s SortedDictionaryKey, Value when you don't care about the value?
If Value
is a reference type, storing it would waste from 4 to 8 bytes, depending on whether the process is 32-bit or 64-bit. If Value
is a value type, it may waste even more.
If you don't need it, you can set Value
to Byte
. You can't go lower than 1 byte even with an empty struct. You can set to any value, probably 0 is a good choice.
Ideally, if all you need is a set, you should use a set.
There's a SortedSet<T>
in .NET 4.0+ which uses a tree internally. In fact, SortedDictionary<TKey, TValue>
uses SortedSet<KeyValuePair<TKey, TValue>>
internally.
The set counterpart of SortedList<TKey, TValue>
is a List<T>
, I guess. You'll just need to use binary search and insert values into sorted positions. Implementing ISet<T>
should be simple.
Related Topics
What's the Role of Gethashcode in the Iequalitycomparer<T> in .Net
Return Content with Ihttpactionresult for Non-Ok Response
Uploading and Downloading Large Files in ASP.NET Core 3.1
Best Practices for Serializing Objects to a Custom String Format for Use in an Output File
Methodinvoker VS Action for Control.Begininvoke
Excel Error Hresult: 0X800A03Ec While Trying to Get Range with Cell's Name
How to Determine a Session Variable Is Null or Empty in C#
C# Pass Lambda Expression as Method Parameter
Get Cell Value from a Datatable in C#
Practical Usage of Virtual Functions in C#
Deserializing Heterogenous JSON Array into Covariant List<> Using JSON.Net
String.Isnullorwhitespace in Linq Expression
Why Does Environment.Exit() Not Terminate the Program Any More
Rotate - Transposing a List<List<String>> Using Linq C#
Differences Between Expandoobject, Dynamicobject and Dynamic