Checking all entries from one Dictionary are in another Dictionary - c#

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

Related

How to get Distinct keys of all child dictionary elements of all parent dictionary values

I have a dictionary like this...
Dictionary<string, Dictionary<string, double>>
How to get the list of all Distinct or unique child dictionary keys from all dictionaries of all parent dictionary values (parent dictionary values is nothing but child dictionaries)?
which is the fastest way of doing this in C#?
It's really easy using LINQ:
var result = myDict.Values.SelectMany(x => x.Keys)
.Concat(myDict.Keys)
.Distinct()
.ToList();
but even without LINQ it's super easy when you use HashSet<string>:
var set = new HashSet<string>();
foreach(var outerItem in myDict)
{
set.Add(outerItem.Key);
foreach(var innerKey in item.Value.Keys)
{
set.Add(innerKey);
}
}
HashSet<T> will only keep distinct items, so adding the same string twice won't make any difference.
PS. Next time you should try writing the code first, and ask question when you run into issue you can't overcome by yourself. Stack Overflow is not 'I want code, give me code' kind of site.
Then you need to call SelectMany() on Values property of your dictionary and then use Distinct() to get distinct elements from a sequence by using the default equality comparer.
var res = myDict.Values.SelectMany(x => x.Keys).Distinct().ToList();
This code creates a Dictionary with string keys and double values.
Dictionary<string, double> d = new Dictionary<string, double>()
{
};
// Store keys in a List
List<string> list = new List<string>(d.Keys);
// Loop through list
foreach (string k in list)
{
//From here you can choose distinct key
}
If I'm reading this right:
IEnumerable<string> uniqueChildKeys = dictOfDicts
.SelectMany(d => d.Value.Keys)
.Distinct();

Concat two dictionaries so that original's shared keys are updated

Say I have two dictionaries:
Dictionary<string, string> orig = new Dictionary <string, string>();
orig.Add("one", "value one");
orig.Add("two", "");
orig.Add("three", "");
Dictionary<string, string> newDict = new Dictionary <string, string>();
newDict.Add("one", "this value should not be added");
newDict.Add("two", "value two");
newDict.Add("three", "value three");
How can I merge the two dictionaries so that the resulting dictionary updates the keys only where their corresponding values are empty? Additionally, the merge should not add any keys that are present in new but not in orig. That is, "one" still has the value "value one" while "two" and "three" are updated with the values from new.
I tried using orig.Concat(new);, but that leaves me with the original dictionary. Perhaps this can be done with LINQ?
Try:
orig = orig.Keys.ToDictionary(c => c, c=>(orig[c] == "" ? newDict[c] : orig[c]));
This loop does what you want efficiently and readable:
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (var keyVal in orig)
{
if (!string.IsNullOrEmpty(keyVal.Value))
result.Add(keyVal.Key, keyVal.Value);
else
{
string val2;
if (newDict.TryGetValue(keyVal.Key, out val2))
result.Add(keyVal.Key, val2);
else
result.Add(keyVal.Key, "");
}
}
Result:
one, value one
two, value two
three, value three
I would use the foreach
foreach (var pair in orig.Where(x=> string.IsNullOrEmpty(x.Value)).ToArray())
{
orig[pair.Key] = newone[pair.Key];
}
Extension method 'one-liners' are great when they help to clarify intention, but for something like this, I would be inclined to write a small method with an explicit loop that does the desired operation. I think this is much cleaner than creating a new dictionary using various extension method transformations:
public void PopulateMissingValues(Dictionary<string, string> orig, Dictionary<string, string> newDict)
{
foreach (var pair in orig.Where(p => p.Value == string.Empty))
{
string newValue;
if (newDict.TryGetValue(pair.Key, out newValue))
orig[pair.Key] = newValue;
}
}

Can I compare the keys of two dictionaries?

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)...

How to extract List<int> from Dictionary<int, string>?

I have a method that takes a List<int>, which is a list of IDs. The source of my data is a Dictionary<int, string> where the integers are what I want a list of. Is there a better way to get this than the following code?
var list = new List<int>();
foreach (var kvp in myDictionary)
{
list.Add(pair.Key);
}
ExecuteMyMethod(list);
You could do
var list = myDictionary.Keys.ToList();
Or
var list = myDictionary.Select(kvp => kvp.Key).ToList();
Yes, you can use the Keys collection in the constructor of the list:
List<int> list = new List<int>(myDictionary.Keys);
Like Guffa said that's some thing which is easy and elegant.
or
List<int> nList = myDictionary.Keys.ToList<int>();

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