Can I compare the keys of two dictionaries? - c#

Using C#, I want to compare two dictionaries to be specific, two dictionaries with the same keys but not same values, I found a method Comparer but I'm not quite sure how can I use it? Is there a way other than iterating through each key?
Dictionary
[
{key : value}
]
Dictionary1
[
{key : value2}
]

If all you want to do is see if the keys are different but not know what they are, you can use the SequenceEqual extension method on the Keys property of each dictionary:
Dictionary<string,string> dictionary1;
Dictionary<string,string> dictionary2;
var same = dictionary1.Count == dictionary2.Count && dictionary1.Keys.SequenceEqual(dictionary2.Keys);
If you want the actual differences, something like this:
var keysDictionary1HasThat2DoesNot = dictionary1.Keys.Except(dictionary2.Keys);
var keysDictionary2HasThat1DoesNot = dictionary2.Keys.Except(dictionary1.Keys);

return dict1.Count == dict2.Count &&
dict1.Keys.All(dict2.ContainsKey);

Try this
public bool SameKeys<TKey, TValue>(IDictionary<TKey, TValue> one, IDictionary<TKey, TValue> two)
{
if (one.Count != two.Count)
return false;
foreach (var key in one.Keys)
{
if (!two.ContainsKey(key))
return false;
}
return true;
}

You can get a collection of the keys and index it, if that helps.
dictionary1.keys[0] == dictionary2.keys[5]
I'm actually not sure if you index it with a number or if you do it with the key itself, so try out both.

You could go with this (depending if you want the intersect or the exclusion):
Dictionary<int, int> dict1 = new Dictionary<int, int>();
Dictionary<int, int> dict2 = new Dictionary<int, int>();
IEnumerable<int> keys1ExceptKeys2 = dict1.Keys.Except(dict2.Keys);
IEnumerable<int> keys2ExceptKeys1 = dict2.Keys.Except(dict1.Keys);
IEnumerable<int> keysIntersect = dict1.Keys.Intersect(dict2.Keys);

You could just:
new HashSet<TKey>(dictionary1.Keys).SetEquals(dictionary2.Keys)
Be careful if dictionary1 uses a different comparer from dictionary2. You'll have to decide whether "equality" means what one or the other dictionary thinks it means (or something else entirely)...

Related

Fastest way to check a Dictionary<> is equal to another [duplicate]

Assuming dictionary keys and values have their equals and hash methods implemented correctly, what is the most succinct and efficient way to test for equality of two dictionaries?
In this context, two dictionaries are said to be equal if they contain the same set of keys (order not important), and for every such key, they agree on the value.
Here are some ways I came up with (there are probably many more):
public bool Compare1<TKey, TValue>(
Dictionary<TKey, TValue> dic1,
Dictionary<TKey,TValue> dic2)
{
return dic1.OrderBy(x => x.Key).
SequenceEqual(dic2.OrderBy(x => x.Key));
}
public bool Compare2<TKey, TValue>(
Dictionary<TKey, TValue> dic1,
Dictionary<TKey, TValue> dic2)
{
return (dic1.Count == dic2.Count &&
dic1.Intersect(dic2).Count().
Equals(dic1.Count));
}
public bool Compare3<TKey, TValue>(
Dictionary<TKey, TValue> dic1,
Dictionary<TKey, TValue> dic2)
{
return (dic1.Intersect(dic2).Count().
Equals(dic1.Union(dic2).Count()));
}
dic1.Count == dic2.Count && !dic1.Except(dic2).Any();
It really depends on what you mean by equality.
This method will test that two dictionaries contain the same keys with the same values (assuming that both dictionaries use the same IEqualityComparer<TKey> implementation).
public bool CompareX<TKey, TValue>(
Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue> dict2)
{
if (dict1 == dict2) return true;
if ((dict1 == null) || (dict2 == null)) return false;
if (dict1.Count != dict2.Count) return false;
var valueComparer = EqualityComparer<TValue>.Default;
foreach (var kvp in dict1)
{
TValue value2;
if (!dict2.TryGetValue(kvp.Key, out value2)) return false;
if (!valueComparer.Equals(kvp.Value, value2)) return false;
}
return true;
}
You could use linq for the key/value comparisons:
public bool Compare<TKey, TValue>(Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue dict2)
{
IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
return dict1.Count == dict2.Count &&
dict1.Keys.All(key => dict2.ContainsKey(key) && valueComparer.Equals(dict1[key], dict2[key]));
}
In addition to #Nick Jones answer, you're going to need to implement gethashcode in the same, order agnostic way. I would suggest something like this:
public override int GetHashCode()
{
var hash = 13;
var orderedKVPList = this.DictProp.OrderBy(kvp => kvp.Key);
foreach (var kvp in orderedKVPList)
{
hash = (hash * 7) + kvp.Key.GetHashCode();
hash = (hash * 7) + kvp.Value.GetHashCode();
}
return hash;
}
I thought the accepted answer would be correct based on what I was reading in the smarthelp for the Except method: "Produces the set difference of two sequences by using the default equality comparer to compare values." But I discovered it is not a good answer.
Consider this code:
Dictionary<string, List<string>> oldDict = new Dictionary<string, List<string>>()
{{"001A", new List<string> {"John", "Doe"}},
{"002B", new List<string> {"Frank", "Abignale"}},
{"003C", new List<string> {"Doe", "Jane"}}};
Dictionary<string, List<string>> newDict = new Dictionary<string, List<string>>()
{{"001A", new List<string> {"John", "Doe"}},
{"002B", new List<string> {"Frank", "Abignale"}},
{"003C", new List<string> {"Doe", "Jane"}}};
bool equal = oldDict.Count.Equals(newDict.Count) && !oldDict.Except(newDict).Any();
Console.WriteLine(string.Format("oldDict {0} newDict", equal?"equals":"does not equal"));
equal = oldDict.SequenceEqual(newDict);
Console.WriteLine(string.Format("oldDict {0} newDict", equal ? "equals" : "does not equal"));
Console.WriteLine(string.Format("[{0}]", string.Join(", ",
oldDict.Except(newDict).Select(k =>
string.Format("{0}=[{1}]", k.Key, string.Join(", ", k.Value))))));
This results in the following:
oldDict does not equal newDict
oldDict does not equal newDict
[001A=[John, Doe], 002B=[Frank, Abignale], 003C=[Doe, Jane]]
As you can see, both "oldDict" and "newDict" are setup exactly the same. And neither the suggested solution nor a call to SequenceEqual works properly. I wonder if it is a result of the Except using lazy loading or the way the comparer is setup for the Dictionary. (Although, looking at the structure and reference explanations suggest it should.)
Here's the solution I came up with. Note that the rule I used is as follows: two dictionaries are equal if both contain the same keys and the values for each key match. Both keys and values must be in the same sequential order. And my solution may not be the most efficient, since it relies on iterating through the entire set of keys.
private static bool DictionaryEqual(
Dictionary<string, List<string>> oldDict,
Dictionary<string, List<string>> newDict)
{
// Simple check, are the counts the same?
if (!oldDict.Count.Equals(newDict.Count)) return false;
// Verify the keys
if (!oldDict.Keys.SequenceEqual(newDict.Keys)) return false;
// Verify the values for each key
foreach (string key in oldDict.Keys)
if (!oldDict[key].SequenceEqual(newDict[key]))
return false;
return true;
}
Also see how the results change if:
Key order is not the same. (returns false)
newDict = new Dictionary<string, List<string>>()
{{"001A", new List<string> {"John", "Doe"}},
{"003C", new List<string> {"Doe", "Jane"}},
{"002B", new List<string> {"Frank", "Abignale"}}};
and
Key order matches, but Value does not match (returns false)
newDict = new Dictionary<string, List<string>>()
{{"001A", new List<string> {"John", "Doe"}},
{"002B", new List<string> {"Frank", "Abignale"}},
{"003C", new List<string> {"Jane", "Doe"}}};
If sequence order does not matter, the function can be changed to the following, but there is likely a performance hit.
private static bool DictionaryEqual_NoSort(
Dictionary<string, List<string>> oldDict,
Dictionary<string, List<string>> newDict)
{
// Simple check, are the counts the same?
if (!oldDict.Count.Equals(newDict.Count)) return false;
// iterate through all the keys in oldDict and
// verify whether the key exists in the newDict
foreach(string key in oldDict.Keys)
{
if (newDict.Keys.Contains(key))
{
// iterate through each value for the current key in oldDict and
// verify whether or not it exists for the current key in the newDict
foreach(string value in oldDict[key])
if (!newDict[key].Contains(value)) return false;
}
else { return false; }
}
return true;
}
Check out if the DictionaryEqual_NoSort using the following for newDict (DictionaryEquals_NoSort returns true):
newDict = new Dictionary<string, List<string>>()
{{"001A", new List<string> {"John", "Doe"}},
{"003C", new List<string> {"Jane", "Doe"}},
{"002B", new List<string> {"Frank", "Abignale"}}};
Simple O(N) time, O(1) space solution with null checks
The other solutions using Set operations Intersect, Union or Except are good but these require additional O(N) memory for the final resultant dictionary which is just used for counting elements.
Instead, use Linq Enumerable.All to check this. First validate the count of two dictionaries, next, iterate over all D1's Key Value pairs and check if they are equal to D2's Key Value pairs. Note: Linq does allocate memory for a collection iterator but it's invariant of the collection size - O(1) space. Amortized complexity for TryGetValue is O(1).
// KV is KeyValue pair
var areDictsEqual = d1.Count == d2.Count && d1.All(
(d1KV) => d2.TryGetValue(d1KV.Key, out var d2Value) && (
d1KV.Value == d2Value ||
d1KV.Value?.Equals(d2Value) == true)
);
Why d1KV.Value == d2Value? - this is to check if object references are equal. Also, if both are null, d1KV.Value == d2Value will evaluate to true.
Why d1Kv.Value?.Equals(d2Value) == true? - Value?. is for null safe check and .Equals is meant to test equality of two objects based on your object's Equals and HashCode methods.
You can tweak the equality checks as you like. I'm assuming the Dict Values are nullable type to make the solution more generic (eg: string, int?, float?). If it's non-nullable type, the checks could be simplified.
Final note: In C# dictionary, the Keys can't be null. But Values can be null. Docs for reference.
#Allen's answer:
bool equals = a.Intersect(b).Count() == a.Union(b).Count()
is about arrays but as far as IEnumerable<T> methods are used, it can be used for Dictionary<K,V> too.
If two dictionaries contain the same keys, but in different order, should they be considered equal? If not, then the dictionaries should be compared by running enumerators through both simultaneously. This will probably be faster than enumerating through one dictionary and looking up each element in the other. If you have advance knowledge that equal dictionaries will have their elements in the same order, such a double-enumeration is probably the way to go.

C# - Tuple or other multikey variant for Dictionary, but with permutability

I am scratching my head over the following problem.
I want to create a dictionary, which uses multiple keys. I came along the solutions suggesting tuples as the method of choice. I think this i a good way to go. However my problem has the following speciality. I would like to make the keys "permutable" (Sorry, if I am using the wrong slang here). What I mean with this, is the following. I want the result of dict[<key1,key2> to be the same as with dict[<key2,<key1>], because the data that I want to store is invariant to the order of keys.
As an example see the following code, which of course does at the moment not yield the result I am hoping for. I want the result with permuted key to be the same as for the key-tuple.
Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2");
Dictionary<Tuple<string,string>, double> dict = new Dictionary<Tuple<string, string>, double>();
dict.Add(key, 5.0);
Console.WriteLine(dict[key]);
Tuple<string, string> permutedKey = new Tuple<string, string>("Name2", "Name1");
Console.WriteLine(dict[permutedKey]);
The reason for all this, I have to store data, which has to be indexed with two keys, but is essentially always symetrical. So there is no need, to store it two times.
You can define your own custom equality comparer and use it in the dictionary:
class TupleComparer<T> : IEqualityComparer<Tuple<T, T>>
{
public bool Equals(Tuple<T, T> x, Tuple<T, T> y)
{
return object.Equals(x.Item1, y.Item1) && object.Equals(x.Item2, y.Item2) ||
object.Equals(x.Item1, y.Item2) && object.Equals(x.Item2, y.Item1);
}
public int GetHashCode(Tuple<T, T> obj)
{
return obj.Item1.GetHashCode() + obj.Item2.GetHashCode();
}
}
Then, you can create the dictionary passing it an instance of the comparer:
Tuple<string, string> key = new Tuple<string, string>("Name1", "Name2");
Dictionary<Tuple<string,string>, double> dict =
new Dictionary<Tuple<string, string>, double>(new TupleComparer<string>());
dict.Add(key, 5.0);
Console.WriteLine(dict[key]);
var permutedKey = new Tuple<string, string>("Name2", "Name1");
Console.WriteLine(dict[permutedKey]);
You will need to define your own class with two elements and implement IComparable where CompareTo will be written as per you requirement. Then use that class as Key for your Dictionary. Also, please override method GetHashCode too.
Is comparing List<string> a viable option for your use case? If so, I'd recommend this stack overflow anser:
Compare two List<T> objects for equality, ignoring order
If you can't use List<string>, then I'd agree with rbaghbanli's answer.

Checking all entries from one Dictionary are in another Dictionary

i have two Dictionarys A & B, i want to see if all entries in A exist in B. In the past i've compared Lists using the following:
var set1 = new HashSet<String>(list1);
var set2 = new HashSet<String>(list2);
return set1.SetEquals(set2);
What i have thought to do is simply loop over each value in Dictionary A using:
dictA.TryGetValue(dictBvalue, out item)
this will return null on the item var if the value isn't there, but this seems a little long winded.
Is there a quick and effcient way of comparing dictionaries?
Thanks.
You could use All extension and do this.
var allexist = list1.All(x=> list2.ContainsKey(x.Key) && list2[x.Key] == x.Value)
here is the solution if you want to loop over each value
Dictionary<string, string> dictA = new Dictionary<string, string>();
Dictionary<string, string> dictB = new Dictionary<string, string>();
bool allexist = true;
foreach (var itemA in dictA)
{
if (!dictB.ContainsKey(itemA.Key))
{
allexist = false;
}
}
Actually, you asked for a method comparing dictionaries but your code example refer to HashSet which is different.
For HashSets, you can use IsSubsetOf and SetEquals methods.
To compare dictionaries, you can use DictionaryEquals method from this answer

I need to create a dictionary where each key can map to several values

Im trying to figure out how I can create something similar to a dictionary, but where each key can map to several values.
Basically what I need is to be able to assign multiple values to the same key without knowing in advance how many values each key will correspond to. I also need to be able to add values to an existing key on multiple occasions. It would also be nice if I could detect when a key + value combination already exists.
An example of how the program should work:
list.Add(1,5);
list.Add(3,6);
list.Add(1,7);
list.Add(5,4);
list.Add(1,2);
list.Add(1,5);
This should ideally produce a table like this:
1: 5, 7, 2
3: 6
5: 4
Is there any existing construction in C# that I can use for this or do I have to implement my own class? Implementing the class would probably not be a big problem, but Im a bit short on time so it would be nice if I could use something that already exists.
Quick Solution
As you have already mentioned, a Dictionary would be the best type to use. You can specify both the key type and value type to meet your needs, in your case you want an int key and a List<int> value.
This is easy enough to create:
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>();
The challenge then comes with how you add records, you cannot simply do Add(key, value) because that will cause conflict which duplicate keys. So you have to first retrieve the list (if it exists) and add to that:
List<int> list = null;
if (dictionary.ContainsKey(key))
{
list = dictionary[key];
}
else
{
list = new List<int>();
dictionary.Add(key, list);
}
list.Add(newValue);
Preferred Solution
This is obviously a few too many lines to use each time you want to add an item, so you would want to throw that into a helper function, or my preference would be to create your own class that extends the functionality of Dictionary. Something like this:
class ListDictionary<T1, T2> : Dictionary<T1, List<T2>>
{
public void Add(T1 key, T2 value)
{
if (this.ContainsKey(key))
{
this[key].Add(value);
}
else
{
List<T2> list = new List<T2>() { value };
this.Add(key, list);
}
}
public List<T2> GetValues(T1 key)
{
if(this.ContainsKey(key))
return this[key];
return null;
}
}
Which you can then use as easy as you originally wanted:
ListDictionary<int, int> myDictionary = new ListDictionary<int, int>();
myDictionary.Add(1,5);
myDictionary.Add(3,6);
//...and so on
Then to get the list of values for your desired key:
List<int> keyValues = myDictionary.GetValues(key);
//check if NULL before using, NULL means the key does not exist
//alternatively you can check if the key exists with if (myDictionary.ContainsKey(key))
You can create a dictionary of Lists quite easily e.g.
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>()
An Alternative if you have created a list of items and want to separate them into groups with different keys, which serves much the same purpose is the Lookup class.
Dictionary<int, List<int>> dictionary = new Dictionary<int, List<int>>();
public void AddIfNotExistInDic(int key, int Value) {
List<int> list = null;
if (dictionary.ContainsKey(key)) {
list = dictionary[key];
}
else {
list = new List<int>();
dictionary.Add(key, list);
}
if (!list.Contains(Value)) {
list.Add(Value);
}
}
You can use Dictionary<TKey, TValue>, the TKey would be int and TValue would be List<int>, You can add as many element in List as it grow autmatically.
Dictionary <int, List<int>> dic = new Dictionary<int, List<int>>();
The way you can access the value would change, you can for instance add element in dictionary like
void AddToYourCustomDictionary(int key, int someValue)
{
if(!dic.ContainsKey(key))
{
dic.Add(key, new List<int>());
dic[key].Add(someValue);
}
else
dic[key].Add(someValue); //Adding element in existing key Value pair
}
To access element in Dictionary Key -> value i.e list,
Console.WriteLine(dic[key][indexOfList]);

How do you sort a dictionary by value?

I often have to sort a dictionary (consisting of keys & values) by value. For example, I have a hash of words and respective frequencies that I want to order by frequency.
There is a SortedList which is good for a single value (say frequency), that I want to map back to the word.
SortedDictionary orders by key, not value. Some resort to a custom class, but is there a cleaner way?
Use LINQ:
Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;
This would also allow for great flexibility in that you can select the top 10, 20 10%, etc. Or if you are using your word frequency index for type-ahead, you could also include StartsWith clause as well.
Use:
using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(
delegate(KeyValuePair<string, string> pair1,
KeyValuePair<string, string> pair2)
{
return pair1.Value.CompareTo(pair2.Value);
}
);
Since you're targeting .NET 2.0 or above, you can simplify this into lambda syntax -- it's equivalent, but shorter. If you're targeting .NET 2.0 you can only use this syntax if you're using the compiler from Visual Studio 2008 (or above).
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
You could use:
var ordered = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
You can sort a Dictionary by value and save it back to itself (so that when you foreach over it the values come out in order):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Sure, it may not be correct, but it works. Hyrum's Law means that this will very likely continue to work.
Looking around, and using some C# 3.0 features we can do this:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
This is the cleanest way I've seen and is similar to the Ruby way of handling hashes.
On a high level, you have no other choice than to walk through the whole Dictionary and look at each value.
Maybe this helps:
http://bytes.com/forum/thread563638.html
Copy/Pasting from John Timney:
Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);
myList.Sort(
delegate(KeyValuePair<string, string> firstPair,
KeyValuePair<string, string> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
You'd never be able to sort a dictionary anyway. They are not actually ordered. The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order. Hence you would need to get the name value pair into a list.
You do not sort entries in the Dictionary. Dictionary class in .NET is implemented as a hashtable - this data structure is not sortable by definition.
If you need to be able to iterate over your collection (by key) - you need to use SortedDictionary, which is implemented as a Binary Search Tree.
In your case, however the source structure is irrelevant, because it is sorted by a different field. You would still need to sort it by frequency and put it in a new collection sorted by the relevant field (frequency). So in this collection the frequencies are keys and words are values. Since many words can have the same frequency (and you are going to use it as a key) you cannot use neither Dictionary nor SortedDictionary (they require unique keys). This leaves you with a SortedList.
I don't understand why you insist on maintaining a link to the original item in your main/first dictionary.
If the objects in your collection had a more complex structure (more fields) and you needed to be able to efficiently access/sort them using several different fields as keys - You would probably need a custom data structure that would consist of the main storage that supports O(1) insertion and removal (LinkedList) and several indexing structures - Dictionaries/SortedDictionaries/SortedLists. These indexes would use one of the fields from your complex class as a key and a pointer/reference to the LinkedListNode in the LinkedList as a value.
You would need to coordinate insertions and removals to keep your indexes in sync with the main collection (LinkedList) and removals would be pretty expensive I'd think.
This is similar to how database indexes work - they are fantastic for lookups but they become a burden when you need to perform many insetions and deletions.
All of the above is only justified if you are going to do some look-up heavy processing. If you only need to output them once sorted by frequency then you could just produce a list of (anonymous) tuples:
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
You could use:
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
Or for fun you could use some LINQ extension goodness:
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
Sorting a SortedDictionary list to bind into a ListView control using VB.NET:
Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End Class
XAML:
<ListView Name="MyDictionaryListView">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The other answers are good, if all you want is to have a "temporary" list sorted by Value. However, if you want to have a dictionary sorted by Key that automatically synchronizes with another dictionary that is sorted by Value, you could use the Bijection<K1, K2> class.
Bijection<K1, K2> allows you to initialize the collection with two existing dictionaries, so if you want one of them to be unsorted, and you want the other one to be sorted, you could create your bijection with code like
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
You can use dict like any normal dictionary (it implements IDictionary<K, V>), and then call dict.Inverse to get the "inverse" dictionary which is sorted by Value.
Bijection<K1, K2> is part of Loyc.Collections.dll, but if you want, you could simply copy the source code into your own project.
Note: In case there are multiple keys with the same value, you can't use Bijection, but you could manually synchronize between an ordinary Dictionary<Key,Value> and a BMultiMap<Value,Key>.
Actually in C#, dictionaries don't have sort() methods.
As you are more interested in sort by values,
you can't get values until you provide them key.
In short, you need to iterate through them using LINQ's OrderBy(),
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy() method here on each item and provide them the IDs.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
You can do one trick:
var sortedDictByOrder = items.OrderBy(v => v.Value);
or:
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
It also depends on what kind of values you are storing: single (like string, int) or multiple (like List, Array, user defined class).
If it's single you can make list of it and then apply sort.
If it's user defined class, then that class must implement IComparable, ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster and more object oriented than LINQ.
Required namespace : using System.Linq;
Dictionary<string, int> counts = new Dictionary<string, int>();
counts.Add("one", 1);
counts.Add("four", 4);
counts.Add("two", 2);
counts.Add("three", 3);
Order by desc :
foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value))
{
// some processing logic for each item if you want.
}
Order by Asc :
foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}
Suppose we have a dictionary as:
Dictionary<int, int> dict = new Dictionary<int, int>();
dict.Add(21,1041);
dict.Add(213, 1021);
dict.Add(45, 1081);
dict.Add(54, 1091);
dict.Add(3425, 1061);
dict.Add(768, 1011);
You can use temporary dictionary to store values as:
Dictionary<int, int> dctTemp = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
{
dctTemp.Add(pair.Key, pair.Value);
}
The easiest way to get a sorted Dictionary is to use the built in SortedDictionary class:
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections will contain the sorted version of sections
Sort and print:
var items = from pair in players_Dic
orderby pair.Value descending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Debug.Log(pair.Key + " - " + pair.Value);
}
Change descending to acending to change sort order
A dictionary by definition is an unordered associative structure that contains only values and keys in a hashable way. In other words has not a previsible way to orderer a dictionary.
For reference read this article from python language.
Link
python data structures
Best way:
var list = dict.Values.OrderByDescending(x => x).ToList();
var sortedData = dict.OrderBy(x => list.IndexOf(x.Value));
The following code snippet sorts a Dictionary by values.
The code first creates a dictionary and then uses OrderBy method to sort the items.
public void SortDictionary()
{
// Create a dictionary with string key and Int16 value pair
Dictionary<string, Int16> AuthorList = new Dictionary<string, Int16>();
AuthorList.Add("Mahesh Chand", 35);
AuthorList.Add("Mike Gold", 25);
AuthorList.Add("Praveen Kumar", 29);
AuthorList.Add("Raj Beniwal", 21);
AuthorList.Add("Dinesh Beniwal", 84);
// Sorted by Value
Console.WriteLine("Sorted by Value");
Console.WriteLine("=============");
foreach (KeyValuePair<string, Int16> author in AuthorList.OrderBy(key => key.Value))
{
Console.WriteLine("Key: {0}, Value: {1}", author.Key, author.Value);
}
}
You can sort the Dictionary by value and get the result in dictionary using the code below:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);
Given you have a dictionary you can sort them directly on values using below one liner:
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);

Categories

Resources