Adding many rows to C# dictionary at once - c#

If I instantiate a new Dictionary I can pass in many values:
Dictionary<string, string> data = new Dictionary<string, string>(){
{ "Key1", "Value1" },
{ "Key2", "Value2" },
{ "Key3", "Value3" },
{ "Key4", "Value4" },
{ "Key5", "Value5" },
}
However, if I already have a Dictionary, such as when it is passed in a parameter, I'm required to call Add for each key-value pair:
data.Add("Key1", "Value1");
data.Add("Key2", "Value2");
data.Add("Key3", "Value3");
data.Add("Key4", "Value4");
data.Add("Key5", "Value5");
I'm wondering if there's a "shorthand" method for adding in a large number of values to an existing Dictionary at one time - preferably natively? An authoritative "no" is welcome if that be the case.
Not as clean as I'm looking for, but these are the two alternatives I know.
This one allows passing many values at once, but requires creating a new Dictionary rather than updating the existing one:
Dictionary<string, string> newData = new Dictionary<string, string>(data)
{
{ "Key6", "Value6"},
{ "Key7", "Value7"},
{ "Key8", "Value8"},
};
It's also possible to create an extension method, but this still calls Add for each row:
public static void AddMany<Tkey, TValue>(this Dictionary<Tkey, TValue> dict, Dictionary<Tkey, TValue> toAdd)
{
foreach(KeyValuePair<Tkey, TValue> row in toAdd)
{
dict.Add(row.Key, row.Value);
}
}

An authoritative "no" is welcome if that be the case.
That be the case.
No, there is not an AddRange or equivalent because there is no practical way to add multiple items to a dictionary at one time. It makes sense for a List to add multiple items at once because they can get copied into the internal array in one command.
For a Dictionary, the hash code of each item must be computed to determine what "bucket" the value will get stored in, so there is by necessity a need to iterate over each item. Thus an AddRange method or its equivalent would at best be syntactic sugar. At worst, one would need to define what would happen if any item in the list already existed. Would it throw an exception? If so, would items that were added before the duplicate stay in the dictionary? If not, would it silently skip the item or replace the duplicate?
These are questions that have no intuitively correct answer and thus have not been pre-defined.

If you frequently need to add multiple items to your dictionary you could make an extension method
public static class DictionaryExtensions
{
public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dic, List<KeyValuePair<TKey, TValue>> itemsToAdd)
{
itemsToAdd.ForEach(x => dic.Add(x.Key, x.Value));
}
}
The above would be fine for bulk adding known-unique items. If you need to be concerned about dupes then you'd want to add sanity checks and perhaps return a list of bools to let you know which succeeded .. but at that point you might as well forego the extension method since much of the convenience would be lost.

You can make an extension to achieve this task.
public static class DictionaryHelper
{
public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> destination, Dictionary<TKey, TValue> source)
{
if (destination == null) destination = new Dictionary<TKey, TValue>();
foreach (var e in source)
{
if (!destination.ContainsKey(e.Key))
destination.Add(e.Key, e.Value);
destination[e.Key] = e.Value;
}
return destination;
}
}
This is a generic function that will accept another dictionary.

Related

Class design for read-only collection properties

I have an IDictionary<string, MyEnum?> collection that needs to be passed to a class to wrap it in a IReadOnlyDictionary<string, MyEnum> (note MyEnum but not MyEnum?).
I have come up with two designs:
Delay the wrapping to IReadOnlyDictionary<string, MyEnum> until property access:
public class MyClass
{
private readonly IEnumerable<KeyValuePair<string, MyEnum?>> _kvps;
public MyClass(IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
_kvps = kvps;
}
public IReadOnlyDictionary<string, MyEnum> Kvps
{
get
{
var filtered = from kvp in _kvps
where kvp.Value.HasValue
select kvp;
return new ReadOnlyDictionary<string, MyEnum>(
filtered.ToDictionary(kvp => kvp.Key, kvp => (MyEnum)kvp.Value);
}
}
}
Eagerly evaluate the collection in constructor
public class MyClass
{
public MyClass(IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
Kvps = ToReadOnly(kvps);
}
public IReadOnlyDictionary<string, MyEnum> Kvps { get; }
private static IReadOnlyDictionary<string, MyEnum> ToReadOnly(
IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
var filtered = from kvp in kvps
where kvp.Value.HasValue
select kvp;
return new ReadOnlyDictionary<string, MyEnum>(
filtered.ToDictionary(kvp => kvp.Key, kvp => (MyEnum)kvp.Value);
}
}
The constructor design section of the Framework Design Guidelines suggests that minimal work should be done in constructors so I am opting for the first approach. However, that means every call to MyClass.Kvps will trigger a copy of _kvps which is not ideal.
I would like to know which is a better approach (or are there other ways) in terms of:
Memory efficiency (ideally only one copy of the collection is stored in MyClass)
Performance (property access should be fast and should not trigger a copy of the KeyValuePairs)
Out of the two requirements - don't copy the key value pairs and don't store two copies - you'll have to break one.
What causes us to look at this and think that there must be a solution is that we see TValue and TValue? and our minds want to see them as being of the same type. But they are not the same type.
It becomes clearer if you imagine that instead of TValue and TValue? that these are two different types, like an int and a string, and we want to project a collection of one to a collection of the other while filtering. For example,
List<string> GetStringsFromNonNegativeInts(List<int> ints)
{
return ints.Where(i=>i>-1).Select(i=>i.ToString()).ToList();
}
That's exactly the same scenario as trying to filter a set of TValue? to a set of TValue, even without the dictionary. It's just harder to see. TValue and TValue? code-blind us.
There are only two ways to do this. One is to copy each time, and the other is to keep two lists in synchronization.
EDIT: If you want the latest source values, best way is to implement your own class that implements IReadOnlyDictionary. Initialize this with a private field of ReadOnlyDictionary<string, MyEnum?>. Each call will do the lookup, and if the key exists AND HasValue, return the value.
Note that this implementation depends on the reference to the original values being passed in as an IReadOnlyDictionary to avoid having to copy values over.
public class MyReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue> where TValue : struct
{
// other methods to implement here...
public MyReadOnlyDictionary(IReadOnlyDictionary<TKey, TValue?> kvps)
{
_kvps = kvps;
}
private IReadOnlyDictionary<TKey, TValue?> _kvps;
new public TValue this[TKey key]
{
get
{
TValue? val = _kvps[key];
if (val.HasValue)
return val.Value;
throw new KeyNotFoundException();
}
}
}

Generalize Method to 'Get' Any Object Property

Say I have a Dictionary object which contains many instances of an object called SomeObject and each SomeObject has properties named Property1 and Property2. Now say I have a method which can return a new Dictionary sorted by Property1. However, I'd like to generalize that method such that I can tell it which property to sort by.
For example, to do this, I know I could easily have two separate methods such as:
public Dictionary<string, SomeObject> SortByProp1(Dictionary<string, SomeObject> dict) { ... }
public Dictionary<string, SomeObject> SortByProp2(Dictionary<string, SomeObject> dict) { ... }
But, I'm wondering if it's possible to combine these into one method in which I can give a parameter to identify which method to return? I don't know of a way to generalize a property like that...
Note: I do realize I could always use something like an if-statement which could be based on a string of the property name, but that doesn't seem like a very elegant, acceptable answer much better than just having two separate methods to begin with.
The method you seek is built into the IEnumerable<T> interface, and is OrderBy, though it might not work out as smothly for a Dictionary as you might like.
Dictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>, so its OrderBy method takes a lambda expression which itself takes a KeyValuePair<TKey, TValue>, and returns a selector method that describes what you're sorting by.
For example, if you have Dictionary<int, Customer>, this will return to you an IEnumerable<KeyValuePair<int, Customer>> sorted by customer name:
myDict.OrderBy(kvp => kvp.Value.Name);
Then to get just the customers themselves in this sorted order, you'd say:
IEnumerable<Customer> orderedByName = myDict.OrderBy(kvp => kvp.Value.Name).Select(kvp => kvp.Value);
Can you try adding a generic type parameter, for the ordering key - and accept a predicate for the ordering?
Such as:
public Dictionary<string, SomeObject> SortByProp<TProp>(Dictionary<string, SomeObject> dict, Expression<SomeObject,TProp> orderPredicate)
{
return dict.OrderBy(orderPredicate);
}
// Usage:
SortByProp(apples, x => x.AppleColor);
SortByProp(oranges, x => x.OrangeType);
You can accept a delegate to select the property:
public Dictionary<string, SomeObject> Sort<TProperty>(Dictionary<string, SomeObject> dict, Func<SomeObject, TProperty> selector) { ... }
You can call it like this:
var sortedDict = Sort(dict, o => o.Property1);

Can we retrieve Dictionary<A,B> elements in the order in which they were inserted?

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.

Getting Proper Type Inference for a more complicated type in a Generic Method

I am working in the .NET 2.0 framework. I have some code working, just want it working a little more elegantly.
I have a need to effectively "mirror" a Dictionary object such that if we start with an object like this
Dictionary<TKey,TValue> StartDictionary;
We can Mirror it like this
Dictionary<TValue,TKey> MirroredDictionary = MirrorDictionary(StartDictionary);
And we would end up with a new dictionary with the values and keys being swapped for each KeyValuePair
Before anyone asks me why: the source dictionary is fairly large and loaded once from reflection calls when my program loads. I don't want to run the same reflection calls a second time to load the mirrored dictionary. Creating a mirrored Dictionary and populating its values and keys the way I came up with seemed to me to be much less costly.
So being the kind of person that hates to rewrite things, I decided to write a Generic method in a helper class I have to do the Mirror using Generics.
Now mind you I've written simple Generic methods before for normal scalar types
Here's what I came up with
public static TOutDic MirrorDictionary<TInDic, TOutDic>(TInDic InDictionary)
where TInDic : IDictionary
where TOutDic : IDictionary
{
Type[] KVPTypes = typeof(TInDic).GetGenericArguments();
Type TKey = KVPTypes[0];
Type TValue = KVPTypes[1];
Type TDic = typeof(Dictionary<,>).MakeGenericType(TValue, TKey);
IDictionary OutDic = (IDictionary)Activator.CreateInstance(TDic);
foreach (DictionaryEntry DE in (IDictionary)InDictionary) OutDic.Add(DE.Value, DE.Key);
return (TOutDic)OutDic;
}
A little bit there but it works, Loads up the Types of the Keys and Values and creates an instance of the mirrored Dictionary
Then just looping through the base DictionaryEntries of the InDictionary it adds the items to the OutDic and returns it casting it to the Type expected
Compiles just fine
Now when i go to call it I would think just like when i call a Generic method for a scalar type I could just using our code snippits above say
Dictionary<TValue,TKey> MirroredDictionary = MirrorDictionary(StartDictionary);
But that does not compile gives me
The type arguments for method MirrorDictionary(TInDic)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
So If I call it instead like this
Dictionary<TValue, TKey> MirrorDic = MirrorDictionary<Dictionary<Tkey, TValue>, Dictionary<TValue,TKey>>(StringDic);
It compiles and works like a charm.
Now the question becomes how do I make it properly infer the Type being passed into this method when the Type being passed in and the Type being passed out are complex types like in this example?
You can make life much easier for the compiler by telling it the key and value types thus:
public static Dictionary<TValue, TKey> MirrorDictionary<TKey, TValue>
(Dictionary<TKey, TValue> source)
{
Dictionary<TValue, TKey> destination = new Dictionary<TValue, TKey>();
foreach (KeyValuePair<TKey, TValue> kvp in source)
{
destination.Add(kvp.Value, kvp.Key);
}
return destination;
}
I don't think you need reflection here at all.
Sample usage:
static void Main(string[] args)
{
Dictionary<int, string> source = new Dictionary<int, string>();
source.Add(3, "foo");
source.Add(4, "bar");
DumpDic(source);
DumpDic(MirrorDictionary(source));
Console.ReadLine();
}
where DumpDic is:
public static void DumpDic<TK, TV>(Dictionary<TK, TV> dic)
{
foreach (KeyValuePair<TK, TV> keyValuePair in dic)
{
Console.WriteLine("{0} => {1}", keyValuePair.Key, keyValuePair.Value);
}
}
Here's a 3.5 solution (you can also use it in 2.0 with VS2008 and LinqBridge)
IDictionary<TValue, TKey> MirrorDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict)
{
return dict.ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
}
And a pure 2.0 solution
IDictionary<TValue, TKey> MirrorDictionary<TKey, TValue>(IDictionary<TKey, TValue> dict)
{
Dictionary<TValue, TKey> newDict = new Dictionary<TValue, TKey>();
foreach(KeyValuePair<TKey, TValue> kvp in dict)
{
newDict.Add(kvp.Value, kvp.Key);
}
return newDict;
}
Type inference should work fine with both solutions (as they have the same signature)
You could define the Out dictionary as an out parameter. Type inference does not look the type of the variable you're assigning to, only the types of the parameters. That's the reason this doesn't compile.
You need to tell it what TValue and TKey are. Unless they are defined up in the signature of the method calling this code, they don't have any specific types. You need to give it something like:
Dictionary<string, int> MirroredDictionary = MirrorDictionary(StartDictionary);

Is there a more elegant way of adding an item to a Dictionary<> safely?

I need to add key/object pairs to a dictionary, but I of course need to first check if the key already exists otherwise I get a "key already exists in dictionary" error. The code below solves this but is clunky.
What is a more elegant way of doing this without making a string helper method like this?
using System;
using System.Collections.Generic;
namespace TestDictStringObject
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, object> currentViews = new Dictionary<string, object>();
StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view1");
StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view2");
StringHelpers.SafeDictionaryAdd(currentViews, "Employees", "view1");
StringHelpers.SafeDictionaryAdd(currentViews, "Reports", "view1");
foreach (KeyValuePair<string, object> pair in currentViews)
{
Console.WriteLine("{0} {1}", pair.Key, pair.Value);
}
Console.ReadLine();
}
}
public static class StringHelpers
{
public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view)
{
if (!dict.ContainsKey(key))
{
dict.Add(key, view);
}
else
{
dict[key] = view;
}
}
}
}
Just use the indexer - it will overwrite if it's already there, but it doesn't have to be there first:
Dictionary<string, object> currentViews = new Dictionary<string, object>();
currentViews["Customers"] = "view1";
currentViews["Customers"] = "view2";
currentViews["Employees"] = "view1";
currentViews["Reports"] = "view1";
Basically use Add if the existence of the key indicates a bug (so you want it to throw) and the indexer otherwise. (It's a bit like the difference between casting and using as for reference conversions.)
If you're using C# 3 and you have a distinct set of keys, you can make this even neater:
var currentViews = new Dictionary<string, object>()
{
{ "Customers", "view2" },
{ "Employees", "view1" },
{ "Reports", "view1" },
};
That won't work in your case though, as collection initializers always use Add which will throw on the second Customers entry.
What's wrong with...
dict[key] = view;
It'll automatically add the key if it's non-existent.
simply
dict[key] = view;
From the MSDN documentation of Dictionary.Item
The value associated with the
specified key. If the specified key is
not found, a get operation throws a
KeyNotFoundException, and a set
operation creates a new element with
the specified key.
My emphasis
As usual John Skeet gets in there with lighting speed with the right answer, but interestingly you could also have written your SafeAdd as an Extension Method on IDictionary.
public static void SafeAdd(this IDictionary<K, T>. dict, K key, T value)...
Although using the indexer is clearly the right answer for your specific problem, another more general answer to the problem of adding additional functionality to an existing type would be to define an extension method.
Obviously this isn't a particularly useful example, but something to bear in mind for the next time you find a real need:
public static class DictionaryExtensions
{
public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict,
TKey key, TValue value)
{
dict[key] = value;
}
}

Categories