Dictionary .Values and .Keys to array (in same order) - c#

Is there an elegant way to get a dictionary's keys and values in the same order? I am worried that if I use dict.Values.ToArray() and dict.Keys.ToArray() (or dict.Select(obj => obj.Key) and dict.Select(obj => obj.Value)), that they won't be in the same order.
The simple way to execute this is:
foreach (var keyAndVal in dict)
{
keyList.Add(keyAndVal.Key);
valueList.Add(keyAndVal.Value);
}
var keyArray = keyList.ToArray();
var valueArray = valueList.ToArray();
To me, this feels like the kind of thing that LINQ was made for (but I know that dictionary iteration order is not guaranteed to stay the same in two different calls). Is there an elegant (i.e. LINQ, etc.) way to get these in the same order?
Thanks a lot for your help.

As vcsjones points out, for a standard dictionary, the Keys and Values collections will be in the same order. However, if you want a method that will create key and value arrays that will always be in the same order, for any implementation of IDictionary<TKey, TValue>, you could do something like this:
var keyArray = new TKey[dict.Count];
var valueArray = new TValue[dict.Count];
var i = 0;
foreach (var keyAndVal in dict)
{
keyArray[i] = keyAndVal.Key;
valueArray[i] = keyAndVal.Value;
i++;
}

Related

How to add keys to hashtable from a List in the same order in C#

I have a integer List List<int> iFaciltyReqId = new List<int>(); and its elements are
I need to order the hashtable below like the above List(need to exclude if the element not exist)
My hashtable is
Result should be hastable keys in the order
1153
1168
1155
1152
1176
676
I tried as below, but the result is not meeting my expectation
foreach (var c in iFaciltyReqId)
{
foreach (var d in ohmItemSeqs.Keys)
{
if (Convert.ToInt32(c) == Convert.ToInt32(d))
{
sortedohmItemSeqs.Add(c, ohmItemSeqs.Values);
}
}
}
and result was
Any help will be appreciated.
I would suggest you simply take your list and return everything that's also in the hash table like so:
var result = yourList.Where(i => yourHashTable.Contains(i)); // works for both HashSet<int> and Hashtable
A Hashtable is fundamentally an unordered data structure, so you'll want to look at alternatives if maintaining order is important.
If you want the order to be determined by insertion, OrderedDictionary may be a suitable option, although that depends on what your other needs for the object are.

Efficient way to find the difference between 2 IEnumerables

I have
IEnumerable<Tuple<string, string>> allInfo
and IEnumerable<string> info1dim. What is a way to find effectively the diff between info1dim and first dim of allInfo. For example :
allInfo = {<"data1", "addinfo1">, <"data2", "addinfo2">, <"data3", "addinfo3">"
and
info1dim = {"data3", "data1", "data4"}
The result I expect is
{"diff4"}
What is the most efficient way to do that?
I don't want to run two loops. The IEnumerables are huge (~100000 elements)
The C# HashSet collection has ExceptWith, UnionWith, and IntersectWith methods. What you want could be done like this.
var set1 = new HashSet<string>(allinfo.Select(t => t.Item1));
var set2 = new HashSet<string>(info1dim);
var set1_but_not_set2 = new HashSet<string>(set1);
set1_but_not_set2.ExceptWith(set2);
var set2_but_not_set1 = new HashSet<string>(set2);
set2_but_not_set1.ExceptWith(set1);
Be careful, though, HashSet is a mutable collection and these functions change the collection. You have O(n) operations here. Constructing the HashSet objects requires iterating; so do the ExceptWith operations.
You could use a LINQ Except() like so:
info1dim.Except(allInfo.Select(i => i.Item1));
Note that Except() uses a HashSet<T> internally (as explained here) so this is still O(n).
Maybe something like this?
var diff = info1dim.Where(x => allInfo.Any(c => c.Item1 == x) == false);
If you store the IEnumerable<Tuple<string, string>> in a Dictionary<string,string> instead it would become ALOT faster! then you could write:
Dictionary<string,string> allInfo;
IEnumerable<string> info1dim;
var diff = info1dim.Where(x => allInfo.ContainsKey(x) == false);
load your info1dim in a HashSet and use Remove foreach item in allInfo :
// n: size of info1dim ; m: size of allInfo
var diff = new HashSet<string> (info1dim); // O(n)
foreach (var tuple in allInfo) // O(m)
diff.Remove (tuple.Item1); // O(1)
I didn't recall of ExceptWith existence before Ollie's answer ; after verifying at the source reference ExceptWith basically do the same (foreach -> Remove) and so should be better ; I keep my code as is as informative support tough

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();

Set of values in one or other list but not both

I am diffing two dictionaries, and I want the set of all keys in or or other dictionary but not both (I don't care about order). Since this only involves the keys, we can do this with the IEnumerables of the keys of the dictionaries.
The easy way, involving 2 passes:
return first.Keys.Except(second.Keys).Concat(second.Keys.Except(first.Keys));
We can concat because the Excepts guarantee the lists will be entirely different.
But I sense there is a better, linqy way to do it.
I prefer a non-LINQy way:
var set = new HashSet<KeyType>(first.Keys);
set.SymmetricExceptWith(second.Keys);
Here's an alternative (but not better) LINQy way to yours:
var result = first.Keys.Union(second.Keys)
.Except(first.Keys.Intersect(second.Keys));
If you're looking for something (possibly) more performant:
var result = new HashSet<KeyType>();
foreach(var firstKey in first.Keys)
{
if(!second.ContainsKey(firstKey))
result.Add(firstKey);
}
foreach(var secondKey in second.Keys)
{
if(!first.ContainsKey(secondKey))
result.Add(secondKey);
}

The order of elements in Dictionary

My question is about enumerating Dictionary elements
// Dictionary definition
private Dictionary<string, string> _Dictionary = new Dictionary<string, string>();
// add values using add
_Dictionary.Add("orange", "1");
_Dictionary.Add("apple", "4");
_Dictionary.Add("cucumber", "6");
// add values using []
_Dictionary["banana"] = 7;
_Dictionary["pineapple"] = 7;
// Now lets see how elements are returned by IEnumerator
foreach (KeyValuePair<string, string> kvp in _Dictionary)
{
Trace.Write(String.Format("{0}={1}", kvp.Key, kvp.Value));
}
In what order will be the elements enumerated? Can I force the order to be alphabetical?
The order of elements in a dictionary is non-deterministic. The notion of order simply is not defined for hashtables. So don't rely on enumerating in the same order as elements were added to the dictionary. That's not guaranteed.
Quote from the doc:
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<TKey, TValue> structure representing a value and its key. The order in which the items are returned is undefined.
You can always use SortedDictionary for that. Note that the dictionary is ordered by Key, by default, unless a comparer has been specified.
I'm skeptic regarding the use of OrderedDictionary for what you want since documentation says that:
The elements of an OrderedDictionary are not sorted by the key, unlike
the elements of a SortedDictionary class.
If you want the elements ordered, use a SortedDictionary. An ordinary hastable/dictionary is ordered only in some sense of the storage layout.
The items will be returned in the order that they happen to be stored physically in the dictionary, which depends on the hash code and the order the items were added. Thus the order will seem random, and as implementations change, you should never depend on the order staying the same.
You can order the items when enumerating them:
foreach (KeyValuePair<string, string> kvp in _Dictionary.OrderBy(k => k.Value)) {
...
}
In framework 2.0 you would first have to put the items in a list in order to sort them:
List<KeyValuePair<string, string>> items = new List<KeyValuePair<string, string>>(_Dictionary);
items.Sort(delegate(KeyValuePair<string, string> x, KeyValuePair<string, string> y) { return x.Value.CompareTo(y.Value); });
foreach (KeyValuePair<string,string> kvp in items) {
...
}
For an OrderedDictionary:
var _OrderedDictionary = new System.Collections.Specialized.OrderedDictionary();
_OrderedDictionary.Add("testKey1", "testValue1");
_OrderedDictionary.Add("testKey2", "testValue2");
_OrderedDictionary.Add("testKey3", "testValue3");
var k = _OrderedDictionary.Keys.GetEnumerator();
var v = _OrderedDictionary.Values.GetEnumerator();
while (k.MoveNext() && v.MoveNext()) {
var key = k.Current; var value = v.Current;
}
Items are returned in the order that they are added.
Associative arrays (aka, hash tables) are unordered, which means that the elements can be ordered in any way imaginable.
HOWEVER, you could fetch the array keys (only the keys), order that alphabetically (via a sort function) and then work on that.
I cannot give you a C# sample because I don't know the language, but this should be enough for you to go on yourself.

Categories

Resources