I am using a ResourceDictionary, but I would like to be able to look up the value or the key with the other item. Each is always unique, so that is not a problem. Is there a type that has this double sided lookup feature?
Not built in, but this is pretty easy to write. I would probably implement IDictionary for this though... You would then dump the ResourceDictionary into your custom type.
public class DoubleLookup<TKey, TValue>
{
private IDictionary<TKey, TValue> keys;
private IDictionary<TValue, TKey> values;
//stuff...
public void Add(TKey key, TValue value)
{
this.keys.Add(key, value);
this.values.Add(value, key);
}
public TKey GetKeyFromValue(TValue value)
{
return this.values[value];
}
public TValue GetValueFromKey(TKey key)
{
return this.keys[key];
}
}
Be very careful when reversing the key/value relationship in a dictionary.
The contract of the dictionary guarantees that, for every value in the collection, there is exactly one key which maps to that value. The keys are unique. But the reverse is not true; for every distinct value, there can be many different keys mapping to that value.
In my own personal code library (written in Java, which is close enough), I have MultiMap class for just this kind of thing. Although the keys are unique, each key can be associated with multiple values. It's exactly identical to a Map>.
When I need to perform value-to-key lookups in a collection, I do something like this:
Map<K, V> lookupTable = ...;
MultiMap<V, K> reverseLookupTable = MapUtil.invert(lookupTable);
V value = ...;
if (reverseLookupTable.containsKey(value)) {
Set<K> keys = reverseLookupTable.get(value);
}
If you use something other than a MultiMap (like a HashMap or Dictionary) as your reverse-lookup table, you run the risk of losing some of your V->K mappings, unless you can guarantee that all keys AND all values in your collection are unique.
EDIT:
Oops. I just noticed that you said that all keys and values in your collection are unique. But I'll leave my answer here anyhow, as a warning for others reading this, who might not be able to provide the same guarantee.
Related
Wondering whether it is possible to have a method with a dictionary parameter where TKey and TValue types are indeterminate. For example, I may want to send a key of int and a value as a custom object, or a key of string and value of a different object.
Can this be done via generic objects, is the best practice with overloads, or is there another method I have not yet located?
public static SortedDictionary<??, ??> CreateSortedDictionary(Dictionary<??, ??> d)
{
SortedDictionary<??, ??> rv = new SortedDictionary<??, ??>();
enter code here...
return rv;
}
Thank you.
You can use generic types for the key and value, which can then be used for both the input and output dictionaries:
public static SortedDictionary<TKey, TValue> CreateSortedDictionary<TKey, TValue>(
Dictionary<TKey, TValue> input)
{
return new SortedDictionary<TKey, TValue>(input);
}
I have a tree of model object which I am displaying in a TreeView using a hierarchical data template. Each model object is converted on the fly to a ViewModel object using a ValueConverter, but the Model's properties are still bound to for the child items in the hierarchical data template.
The problem I have is that the Model objects store their children in dictionaries, and it's specifically the values, rather than the keys that I'm interested in client side. The Dictionary is not Observable, so what I am looking for is - in an ideal world - a way to wrap the Dictionary (or perhaps more specifically the internal ValueCollection that the Dictionary uses on the "Values" property, in order to make it observable.
I've delved into the source of the Dictionary to see if there are any hidden hooks I could reflect, but I can't see anything.
Anyone have a suggestion?
Edit:
The behaviour I want is effectively this:
var nonObservable = new Dictionary<Guid, object>();
var observableDictionary = new ObservableDictionary<Guid, object>(nonObservable);
observableDictionary.CollectionChanged += //Some event handler
nonObservable.Add(Guid.NewGuid, new object());
When I add objects to the non-observable Dictionary, I want a collection changed event on the wrapper to fire. This will probably require some deep reflecting. It's a hacky approach that I would rather avoid, but I don't really like the alternatives either.
You could implement the IDictionary<TKey, TValue> interface. Internally, you'd use a Dictionary, so your class would act as a proxy between the client and the real dictionary. However, you'd also be raising events, like this:
public class ObservableDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private IDictionary<TKey, TValue> _dictionary = //...
public event EventHandler<DictionaryChangedArgs> OnAdded;
public ObservableDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
//wrap an existing dictionary
public ObservableDictionary(IDictionary<Tkey, TValue> dictionary)
{
_dictionary = dictionary;
}
public void Add(TKey key, TValue val) {
_dictionary.Add(key, value);
if(OnAdded != null)
OnAdded(new DictionaryChangedArgs(key, value));
}
}
Edit
Updated the code to reflect your requirement: "wrap an existing dictionary".
The idea seems to be similar to the one presented on dav_i's link.
I was looking for a method in ConcurrentDictionary that allows me to remove an entry by key, if and only if the value is equal to one that I specify, something like the equivalent of TryUpdate, but for removals.
The only method that does this seems to be this method:
ICollection<KeyValuePair<K, V>>.Remove(KeyValuePair<K, V> keyValuePair)
It is the explicit implementation of the ICollection interface, in other words, I have to cast my ConcurrentDictionary to an ICollection first so that I can call Remove.
Remove does exactly what I want, and that cast is no big deal either, also the source code shows it calls the private method TryRemovalInternal with bool matchValue = true, so it all looks nice and clean.
What worries me a bit however is the fact that it is not documented as the optimistically concurrent Remove method of ConcurrentDictionary, so http://msdn.microsoft.com/en-us/library/dd287153.aspx just duplicates the ICollection boilerplate, and the How to: Add and Remove Items from a ConcurrentDictionary does not mention that method either.
Does anyone know if that's the way to go, or is there some other method that I'm missing?
Though it is not an official document, this MSDN blog post can be helpful. The gist of that article: casting to ICollection and calling its Remove method, just as described in the question, is the way to go.
Here's a snippet from the above blog post, which wraps it into a TryRemove extension methods:
public static bool TryRemove<TKey, TValue>(
this ConcurrentDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
if (dictionary == null)
throw new ArgumentNullException("dictionary");
return ((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Remove(
new KeyValuePair<TKey, TValue>(key, value));
}
If you don't need all the bells & whistles of ConcurrentDictionary, you can just declare your type as an IDictionary.
public class ClassThatNeedsDictionary
{
private readonly IDictionary<string, string> storage;
public ClassThatNeedsDictionary()
{
storage = new ConcurrentDictionary<string, string>();
}
public void TheMethod()
{
//still thread-safe
this.storage.Add("key", "value");
this.storage.Remove("key");
}
}
I find this useful in situation in which you only need to add and remove, but still want a thread-safe iteration.
How can we retrieve Dictionary<A,B> elements in the order in which they were inserted? If dictionary doesn't support this then which object should i use which gives the behavior of dictionary but also allows me to get the elements in the order in which they were inserted.
Thanks in advance :)
There is no guarantee that you can retrieve the elements from a Dictionary<TKey, TValue> in order. If this is the behavior that you desire, just encapsulate it into a class:
class DictionaryWithKeysOrderedByInsertion<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> {
private readonly List<TKey> keys = new List<TKey>();
private readonly Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
foreach(var key in keys) {
yield return new KeyValuePair(key, dictionary[key]));
}
}
// etc.
}
Dictionary is unordered, if you want them back in the order they were inserted, you might want to consider the generic Queue
No, dictionary does not have such functionality.
You can
use 2 structures and insert into both at the same time - List/LinkedList to store sequence and dictionary to provide fast lookup.
you can add information about insertion time to entries stored in the dictionary.
All I want is a dictionary which tells me which key it couldn't find, rather than just saying The given key was not present in the dictionary.
I briefly considered doing a subclass with override new this[TKey key], but felt it was a bit hacky, so I've gone with implementing the IDictionary interface, and passing everything through directly to an inner Dictionary, with the only additional logic being in the indexer:
public TValue this[TKey key]
{
get
{
ThrowIfKeyNotFound(key);
return _dic[key];
}
set
{
ThrowIfKeyNotFound(key);
_dic[key] = value;
}
}
private void ThrowIfKeyNotFound(TKey key)
{
if(!_dic.ContainsKey(key))
throw new ArgumentOutOfRangeException("Can't find key [" + key + "] in dictionary");
}
Is this the right/only way to go? Would newing over the this[] really be that bad?
Sounds like a good fit for an extension method:
public static class SomeUtilClass {
public static TValue VerboseGetValue<TKey, TValue>(
this IDictionary<TKey, TValue> data, TKey key)
{
TValue result;
if (!data.TryGetValue(key, out result)) {
throw new KeyNotFoundException(
"Key not found: " + Convert.ToString(key));
}
return result;
}
}
This will then work on all your existing dictionaries whenever you call VerboseGetValue, for example:
var data = new Dictionary<int, string> { { 123, "abc" } };
Console.WriteLine(data.VerboseGetValue(123));
Console.WriteLine(data.VerboseGetValue(456));
Instead of doing ContainsKey and checking for the presence of the key before touching the underlying dictionary, why not do
get {
try {
return _dic[key];
}
catch (ArgumentOutOfRangeException) {
throw new ArgumentOutOfRangeException(......);
}
}
That way, you only pay for the extra checking in the failure case - the success case, which is hopefully more common, doesn't have to do an extra dictionary lookup. This is good for get, but set is more difficult since the default behaviour of set is to always work. If you don't want that then you would need to check for the existence of the key first.
If you want to do this, you are going to have to roll your own in one way or another. But I'm going to question WHY you would want to do this?