How to index the Values property of C# Dictionary - c#

Using the Values property of C# Dictionary,
var myDict = Dictionary < string, object> ;
How would I get the values in
myDict.Values
I tried
var theVales = myDict.Values ;
object obj = theValues[0] ;
But that is a syntax error.
Added:
I am trying to compare the values in two dictionaries that have
the same keys

You can't. The values do not have a fixed order. You could write the values into a new List<object> and index them there, but obviously that's not terribly helpful if the dictionary's contents change frequently.
You can also use linq: myDict.Values.ElementAt(0) but:
The elements will change position as the dictionary grows
It's really inefficient, since it's just calling foreach on the Values collection for the given number of iterations.
You could also use SortedList<TKey, TValue>. That maintains the values in order according to the key, which may or may not be what you want, and it allows you to access the values by key or by index. It has very unfortunate performance characteristics in certain scenarios, however, so be careful about that!
Here's a linq solution to determine if the values for matching keys also match. This only works if you're using the default equality comparer for the key type. If you're using a custom equality comparer, you can do this with method call syntax.
IEnumerable<bool> matches =
from pair1 in dict1
join pair2 in dict2
on pair1.Key equals pair2.Key
select pair1.Value.Equals(pair2.Value)
bool allValuesMatch = matches.All();
If you require that all items in one dictionary have a matching item in the other, you could do this:
bool allKeysMatch = new HashSet(dict1.Values).SetEquals(dict2.ValueS);
bool dictionariesMatch = allKeysMatch && allValuesMatch;

Well, you could use Enumerable.ElementAt if you really had to, but you shouldn't expect the order to be stable or meaningful. Alternatively, call ToArray or ToList to take a copy.
Usually you only use Values if you're going to iterate over them. What exactly are you trying to do here? Do you understand that the order of entries in a Dictionary<,> is undefined?
EDIT: It sounds like you want something like:
var equal = dict1.Count == dict2.Count &&
dict1.Keys.All(key => ValuesEqual(key, dict1, dict2));
...
private static bool ValuesEqual<TKey, TValue>(TKey key,
IDictionary<TKey, TValue> dict1,
IDictionary<TKey, TValue> dict2)
{
TValue value1, value2;
return dict1.TryGetValue(out value1) && dict2.TryGetValue(out value2) &&
EqualityComparer<TValue>.Default.Equals(value1, value2);
}
EDIT: Note that this isn't as fast as it could be, because it performs lookups on both dictionaries. This would be more efficient, but less elegant IMO:
var equal = dict1.Count == dict2.Count &&
dict1.All(pair => ValuesEqual(pair.Key, pair.Value, dict2));
...
private static bool ValuesEqual<TKey, TValue>(TKey key, TValue value1,
IDictionary<TKey, TValue> dict2)
{
TValue value2;
return dict2.TryGetValue(out value2) &&
EqualityComparer<TValue>.Default.Equals(value1, value2);
}

To add to #JonSkeet's answer, Dictionary<TKey, TValue> is backed by a HashTable, which is an un-ordered data structure. The index of the values is therefore meaningless- it is perfectly valid to get, say, A,B,C with one call and C,B,A with the next.
EDIT:
Based on the comment you made on JS's answer ("I am trying to compare the values in two dictionaries with the same keys"), you want something like this:
public boolean DictionariesContainSameKeysAndValues<TKey, TValue>(Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue> dict2) {
if (dict1.Count != dict2.Count) return false;
for (var key1 in dict1.Keys)
if (!dict2.ContainsKey(key1) || !dict2[key1].Equals(dict1[key1]))
return false;
return true;
}

You could use an Indexer propertie to lookup the string Key.
It is still not an Index but one more way:
using System.Collections.Generic;
...
class Client
{
private Dictionary<string, yourObject> yourDict
= new Dictionary<string, yourObject>();
public void Add (string id, yourObject value)
{ yourDict.Add (id, value); }
public string this [string id] // indexer
{
get { return yourDict[id]; }
set { yourDict[id] = value; }
}
}
public class Test
{
public static void Main( )
{
Client client = new Client();
client.Add("A1",new yourObject() { Name = "Bla",...);
Console.WriteLine ("Your result: " + client["A1"]); // indexer access
}
}

Related

Pre order generic list C#

I'm looking for a sorted list in C#, but when I inserting a item not sorting after insert all.
Neither SortedList nor Dictionary are suitable because I may have duplicate keys.
For example:
list.Insert(1001, v1);
list.Insert(1002, v2);
list.Insert(1002, v3);
list.Insert(1003, v4);
One possibility is to write a custom comparer which would allow duplicate keys in your collection:
public class DuplicateKeyComparer<TKey> : IComparer<TKey> where TKey : IComparable
{
public int Compare(TKey x, TKey y)
{
var res = x.CompareTo(y);
return res == 0 ? 1 : res;
}
}
and then use a SortedList<TKey, TValue>:
var comparer = new DuplicateKeyComparer<int>();
var list = new SortedList<int, string>(comparer);
list.Add(1001, "v1");
list.Add(1002, "v2");
list.Add(1002, "v3");
list.Add(1003, "v4");
Obviously there are culprits with this approach that you should be aware of - you will never be able to remove any key from this collection. So if you intend to use list.Remove(1002) as an example, then you will need an alternative approach.

Remove from Dictionary by Key and Retrieve Value

Is there a way to remove an entry from a Dictionary (by Key) AND retrieve its Value in the same step?
For example, I'm calling
Dictionary.Remove(Key);
but I also want it to return the Value at the same time. The function only returns a bool.
I know I can do something like
Value = Dictionary[Key];
Dictionary.Remove(Key);
but it seems like this will search the dictionary twice (once to get the value, and another time to remove it from the dictionary). How can I (if possible) do both WITHOUT searching the dictionary twice?
Starting with .NET Core 2.0, we have:
public bool Remove (TKey key, out TValue value);
https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.remove?view=netcore-2.0#System_Collections_Generic_Dictionary_2_Remove__0__1__
Note this API hasn't been included in .NET Standard 2.0 and .NET Framework 4.7.
Because they both have the desired missing method I tried Microsoft's ConcurrentDictionary and C5 from University of Copenhagen http://www.itu.dk/research/c5/ and I can tell with, at least with my use case it was super slow (I mean 5x - 10x slower) compared to Dictionary.
I think C5 is sorting both keys and values all the time and Concurrent Dictionary is "too worried" about the calling thread.. I am not here to discuss why those two incarnations of Dictionary are slow.
My algorithm was seeking and replacing some entries whereas the first keys would be removed and new keys would be added (some sort of Queue)...
The only think left to do was to modify original .Net mscorelib's Dictionary. I downloaded the source code from Microsoft and included the Dictionary class in my source code. To compile I also need to drag along just the HashHelpers class and ThrowHelper class. All that was left was to comment out some lines (e.g. [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))] and some resource fetching). Obviously I had to add the missing method to the copied class. Also do not try to compile Microsoft Source code you will be doing that for hours, I was lucky enough to get it going.
public bool Remove(TKey key, out TValue value)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets != null)
{
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int bucket = hashCode % buckets.Length;
int last = -1;
for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next)
{
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
{
if (last < 0)
{
buckets[bucket] = entries[i].next;
}
else
{
entries[last].next = entries[i].next;
}
entries[i].hashCode = -1;
entries[i].next = freeList;
entries[i].key = default(TKey);
value = entries[i].value;
entries[i].value = default(TValue);
freeList = i;
freeCount++;
version++;
return true;
}
}
}
value = default(TValue);
return false;
}
Lastly I modified the namespace to System.Collection.Generic.My
In my algorithm I only had two lines where I was getting the value than remove it in the next line.. replaced that with the new method and obtained a steady performance gain of 7%-10%.
Hope it helps this use case and any other cases where re-implementing Dictionary from scratch is just not what one should do.
Even though this is not what the OP has asked for, I could not help myself but post a corrected extension method:
public static bool Remove<TKey, TValue>(this Dictionary<TKey, TValue> self, TKey key, out TValue target)
{
self.TryGetValue(key, out target);
return self.Remove(key);
}
The concurrentDictionary has a TryRemove method that attempts to remove and return the value that has the specified key from the System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.
It returns the default value of the TValue type if key does not exist.
https://msdn.microsoft.com/en-us/library/dd287129(v=vs.110).aspx
You can do it with an Extension method:
public static string GetValueAndRemove<TKey, TValue>(this Dictionary<int, string> dict, int key)
{
string val = dict[key];
dict.Remove(key);
return val;
}
static void Main(string[] args)
{
Dictionary<int, string> a = new Dictionary<int, string>();
a.Add(1, "sdfg");
a.Add(2, "sdsdfgadfhfg");
string value = a.GetValueAndRemove<int, string>(1);
}
You can extend the class to add that functionality:
public class PoppableDictionary<T, V> : Dictionary<T, V>
{
public V Pop(T key)
{
V value = this[key];
this.Remove(key);
return value;
}
}

Retrieving the key of a value from a hash table c#

I have a hash table that contains values of a^j. j is the key and a^j is the value.
I am now calculating another value a^m. I basically want to see if a^m is in the hash table.
I used the ContainsValue fn. to find the value. How would i go about finding out the key of the value?
Here is a little snippet of where i want to implement the search for the value.
Dictionary<BigInteger, BigInteger> b = new Dictionary<BigInteger, BigInteger>();
***add a bunch of BigIntegers into b***
for(int j=0; j < n; j++)
{
z = q* BigInteger.ModPow(temp,j,mod);
***I want to implement to search for z in b here****
}
Does this change anything? the fact that i am searching while inside a for loop?
The fastest way is probably to iterate through the hashtable's DictionaryEntry items to find the value, which in turn gives you the key. I don't see how else to do it.
Firstly, you should absolutely be using Dictionary<TKey, TValue> instead of Hashtable - if you're using BigInteger from .NET 4, there's no reason not to use generic collections everywhere you can. Chances are for the most part you'd see no difference in how it's used - just create it with:
Dictionary<BigInteger, BigInteger> map =
new Dictionary<BigInteger, BigInteger>();
to start with. One thing to watch out for is that the indexer will throw an exception if the key isn't present in the map - use TryGetValue to fetch the value if it exists and a bool to say whether or not it did exist.
As for finding the key by value - there's no way to do that efficiently from a Dictionary. You can search all the entries, which is most easily done with LINQ:
var key = map.Where(pair => pair.Value == value)
.Select(pair => pair.Key)
.First();
but that will iterate over the whole dictionary until it finds a match, so it's an O(n) operation.
If you want to do this efficiently, you should keep two dictionaries - one from a to a^j and one from a^j to a. When you add an entry, add it both ways round. Somewhere on Stack Overflow I've got some sample code of a class which does this for you, but I doubt I'd be able to find it easily. EDIT: There's one which copes with multiple mappings here; the "single mapping" version is in the answer beneath that one.
Anyway, once you've got two dictionaries, one in each direction, it's easy - obviously you'd just lookup a^m as a key in the second dictionary to find the original value which created it.
Note that you'll need to consider whether it's possible for two original keys to end up with the same value - at that point you obviously wouldn't be able to have both mappings in one reverse dictionary (unless it was a Dictionary<BigInteger, List<BigInteger>> or something similar).
Edit: Changed to use Dictionary<TKey, TValue>
Dictionary<TKey, TValue> is an IEnumerable<KeyValuePair<TKey, TValue>>. If you do a foreach over it directly, you can get both the key and value for each entry.
class SomeType
{
public int SomeData = 5;
public override string ToString()
{
return SomeData.ToString();
}
}
// ...
var blah = new Dictionary<string, SomeType>();
blah.Add("test", new SomeType() { SomeData = 6 });
foreach (KeyValuePair<string, SomeType> item in blah)
{
if(e.Value.SomeData == 6)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
}
If you have a newer version of the .Net framework, you could use Linq to find your matches, and place them in their own collection. Here's a code sample showing a little bit of Linq syntax:
using System;
using System.Collections;
using System.Linq;
class SomeType
{
public int SomeData = 5;
public override string ToString()
{
return SomeData.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var blah = new Dictionary<string, SomeType>();
blah.Add("test", new SomeType() { SomeData = 6 });
// Build an enumeration of just matches:
var entriesThatMatchValue = blah
.Where(e => e.Value.SomeData == 6);
foreach (KeyValuePair<string, SomeType> item in entriesThatMatchValue)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
// or: ...
// Build a sub-enumeration of just keys from matches:
var keysThatMatchValue = entriesThatMatchValue.Select(e => e.Key);
// Build a list of keys from matches in-line, using method chaining:
List<string> matchingKeys = blah
.Where(e => e.Value.SomeData == 6)
.Select(e => e.Key)
.ToList();
}
}
private object GetKeyByValue(object searchValue)
{
foreach (DictionaryEntry entry in myHashTable)
{
if (entry.Value.Equals(searchValue))
{
return entry.Key;
}
}
return null;
}

How do I use HashSet<T> as a dictionary key?

I wish to use HashSet<T> as the key to a Dictionary:
Dictionary<HashSet<T>, TValue> myDictionary = new Dictionary<HashSet<T>, TValue>();
I want to look up values from the dictionary such that two different instances of HashSet<T> that contain the same items will return the same value.
HashSet<T>'s implementations of Equals() and GetHashCode() don't seem to do this (I think they're just the defaults). I can override Equals() to use SetEquals() but what about GetHashCode()? I feel like I am missing something here...
You could use the set comparer provided by HashSet<T>:
var myDictionary = new Dictionary<HashSet<T>, TValue>(HashSet<T>.CreateSetComparer());
digEmAll's answer is clearly the better choice in practice, since it uses built in code instead of reinventing the wheel. But I'll leave this as a sample implementation.
You can use implement an IEqualityComparer<HashSet<T>> that uses SetEquals. Then pass it to the constructor of the Dictionary. Something like the following(Didn't test it):
class HashSetEqualityComparer<T>: IEqualityComparer<HashSet<T>>
{
public int GetHashCode(HashSet<T> hashSet)
{
if(hashSet == null)
return 0;
int h = 0x14345843; //some arbitrary number
foreach(T elem in hashSet)
{
h = unchecked(h + hashSet.Comparer.GetHashCode(elem));
}
return h;
}
public bool Equals(HashSet<T> set1, HashSet<T> set2)
{
if(set1 == set2)
return true;
if(set1 == null || set2 == null)
return false;
return set1.SetEquals(set2);
}
}
Note that the hash function here is commutative, that's important because the enumeration order of the elements in the set is undefined.
One other interesting point is that you can't just use elem.GetHashCode since that will give wrong results when a custom equality comparer was supplied to the set.
You can provide a IEqualityComparer<HashSet<T>> to the Dictionary constructor and make the desired implementation in that comparer.

What's the fastest way to copy the values and keys from one dictionary into another in C#?

There doesn't seem to be a dictionary.AddRange() method. Does anyone know a better way to copy the items to another dictionary without using a foreach loop.
I'm using the System.Collections.Generic.Dictionary. This is for .NET 2.0.
There's the Dictionary constructor that takes another Dictionary.
You'll have to cast it IDictionary, but there is an Add() overload that takes KeyValuePair<TKey, TValue>. You're still using foreach, though.
There's nothing wrong with a for/foreach loop. That's all a hypothetical AddRange method would do anyway.
The only extra concern I'd have is with memory allocation behaviour, because adding a large number of entries could cause multiple reallocations and re-hashes. There's no way to increase the capacity of an existing Dictionary by a given amount. You might be better off allocating a new Dictionary with sufficient capacity for both current ones, but you'd still need a loop to load at least one of them.
var Animal = new Dictionary<string, string>();
one can pass existing animal Dictionary to the constructor.
Dictionary<string, string> NewAnimals = new Dictionary<string, string>(Animal);
For fun, I created this extension method to dictionary. This should do a deep copy wherever possible.
public static Dictionary<TKey, TValue> DeepCopy<TKey,TValue>(this Dictionary<TKey, TValue> dictionary)
{
Dictionary<TKey, TValue> d2 = new Dictionary<TKey, TValue>();
bool keyIsCloneable = default(TKey) is ICloneable;
bool valueIsCloneable = default(TValue) is ICloneable;
foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
{
TKey key = default(TKey);
TValue value = default(TValue);
if (keyIsCloneable)
{
key = (TKey)((ICloneable)(kvp.Key)).Clone();
}
else
{
key = kvp.Key;
}
if (valueIsCloneable)
{
value = (TValue)((ICloneable)(kvp.Value)).Clone();
}
else
{
value = kvp.Value;
}
d2.Add(key, value);
}
return d2;
}
If you're dealing with two existing objects, you might get some mileage with the CopyTo method: http://msdn.microsoft.com/en-us/library/cc645053.aspx
Use the Add method of the other collection (receiver) to absorb them.
I don't understand, why not using the Dictionary( Dictionary ) (as suggested by ageektrapped ).
Do you want to perform a Shallow Copy or a Deep Copy? (that is, both Dictionaries pointing to the same references or new copies of every object inside the new dictionary?)
If you want to create a new Dictionary pointing to new objects, I think that the only way is through a foreach.
For a primitive type dictionary:
public void runIntDictionary()
{
Dictionary<int, int> myIntegerDict = new Dictionary<int, int>() { { 0, 0 }, { 1, 1 }, { 2, 2 } };
Dictionary<int, int> cloneIntegerDict = new Dictionary<int, int>();
cloneIntegerDict = myIntegerDict.Select(x => x.Key).ToList().ToDictionary<int, int>(x => x, y => myIntegerDict[y]);
}
or with an Object that implement ICloneable:
public void runObjectDictionary()
{
Dictionary<int, number> myDict = new Dictionary<int, number>() { { 3, new number(3) }, { 4, new number(4) }, { 5, new number(5) } };
Dictionary<int, number> cloneDict = new Dictionary<int, number>();
cloneDict = myDict.Select(x => x.Key).ToList().ToDictionary<int, number>(x => x, y => myDict[y].Clone());
}
public class number : ICloneable
{
public number()
{
}
public number(int newNumber)
{
nr = newnumber;
}
public int nr;
public object Clone()
{
return new number() { nr = nr };
}
public override string ToString()
{
return nr.ToString();
}
}
The reason AddRange is not implemented on Dictionary is due to the way in which a hashtable (i.e. Dictionary) stores its entries: They're not contiguous in memory as we see in an array or a List, instead they're fragmented across multiple hash buckets, so you cannot block-copy the whole range into a List or you'll get a bunch of empty entries which the Dictionary usually hides from you, the user, through its interface. AddRange assumes a single contiguous range of valid data and can therefore use a fast copy implementation e.g.Array.Copy (like C's memcpy).
Due to this fragmentation, we are left no choice but to iterate through the Dictionary's entries manually in order to extract valid keys and values into a single contiguous List or array. This can be confirmed in Microsoft's reference implementation, where CopyTo is implemented using for.

Categories