I want to make arithmetic operations between dictionaries with numbers as value.
This is my code:
public class DictionaryOperation {
public static Dictionary<TKey, double> Add<TKey>(Dictionary<TKey, double> d1, Dictionary<TKey, double> d2) {
Dictionary<TKey, double> result = new Dictionary<TKey, double>();
foreach (TKey key in d1.Keys) {
if (d2.ContainsKey(key))
result[key] = d1[key] + d2[key];
else
result[key] = d1[key];
}
foreach (TKey key in d2.Keys) {
if (!result.ContainsKey(key))
result[key] = d2[key];
}
return result;
}
}
I would like to know if I can create only one method for any numeric type (int float, decimal, ...) or do I have to create one method per numeric type, which means there will be the same code in each methods.
I want to be able to do this:
Dictionary<string, int> ints = DictionaryOperation.Add(new Dictionary<string, int>(), new Dictionary<string, int>());
Dictionary<string, float> floats = DictionaryOperation.Add(new Dictionary<string, float>(), new Dictionary<string, float>());
You can avoid writing the same Method for every numeric type by using generics. You already have a generic key in your dictionary. The only thing missing is the generic value. Change your method to use a generic dictionary value:
public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2)
where TValue : IComparable
The problem is, that there is no type constraint that allows only numbers (or objects that can be added with the + operator). I used IComparable in the line above because all numeric types are comparable.
The next problem is, the IComparable does not help when trying to use the + operator. For this you can use dynamics like so:
dynamic a = d1[key];
dynamic b = d2[key];
result[key] = a + b;
Now you can use the method for all types that implement IComparable. BUT you have no compile time safety. That means you will get runtime errors for all types that do not implement the + operator.
This problem is already described here:
C# Adding two Generic Values
Here the full method:
public static Dictionary<TKey, TValue> Add<TKey, TValue>(Dictionary<TKey, TValue> d1, Dictionary<TKey, TValue> d2)
where TValue : IComparable
{
Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
foreach (TKey key in d1.Keys) {
if (d2.ContainsKey(key))
{
dynamic a = d1[key];
dynamic b = d2[key];
result[key] = a + b;
}
else
result[key] = d1[key];
}
foreach (TKey key in d2.Keys) {
if (!result.ContainsKey(key))
result[key] = d2[key];
}
return result;
}
Related
I have couple of methods and it keeps on expanding. So, I am planning to make it generic. Can anyone please help me with that. Atleast the method definition.
private static Dictionary<string, class1> PToDictionary(MapField<string, class1Proto> keyValuePairs)
{
Dictionary<string, class1> keyValues = new();
foreach (var pair in keyValuePairs)
{
**keyValues[pair.Key] = pToR(pair.Value);**
}
return keyValues;
}
My another method is :
private static Dictionary<Uri, class2> PToDictionary1(MapField<string, class2Proto> keyValuePairs)
{
Dictionary<string, class2> keyValues = new();
foreach (var pair in keyValuePairs)
{
**keyValues[new Uri(pair.Key)] = pToR1(pair.Value);**
}
return keyValues;
}
How can I make this generic so that when more methods are added, I dont need to add code.
I was thinking something like this, but errors are :
// Not sure how to call this method after Func is there
private static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(MapField<TKeyProto, TValueProto> keyValuePairs, Func<TKeyProto, TKey> keyFunc, Func<TValueProto, TValue> valueFunc)
{
//How can I generalize my above method ?
}
Can someone help me complete the method ?
You don't need an extra method at all. LINQ already provides everything you need, combined with the fact that MapField implements IDictionary<TKey, TValue> (and therefore IEnumerable<KeyValuePair<TKey, TValue>>.
You'd just call:
var dictionary = repeatedField.ToDictionary(
pair => ConvertKey(pair.Key), pair => ConvertValue(pair.Value));
(where ConvertKey would be whatever code you want to convert the repeated field key into the dictionary key, and likewise for ConvertValue).
Sample calls:
var d1 = repeatedField1.ToDictionary(pair => pair.Key, pair => pToR(pair.Value));
var d2 = repeatedField2.ToDictionary(
pair => new Uri(pair.Key), pair => pToR1(pair.Value));
... but you may be able to remove the pToR and pToR1 methods anyway. (It's hard to tell without information about what they're doing...)
You can use the following method to convert MapField<TKeyProto, TValueProto> to Dictionary<TKey, TValue>:
public static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(
MapField<TKeyProto, TValueProto> keyValuePairs,
Func<TKeyProto, TKey> mapKey,
Func<TValueProto, TValue> mapValue
)
{
Dictionary<TKey, TValue> keyValues = new();
foreach (var pair in keyValuePairs)
{
keyValues[mapKey(pair.Key)] = mapValue(pair.Value);
}
return keyValues;
}
Here, mapKey is a function that converts MapField's key to a dictionary key. Similarly, mapValue converts MapField's value to a dictionary value.
Another way is to make usage of LINQ ToDictionary extension method:
public static Dictionary<TKey, TValue> PToDictionary<TKey, TValue, TKeyProto, TValueProto>(
MapField<TKeyProto, TValueProto> keyValuePairs,
Func<TKeyProto, TKey> mapKey,
Func<TValueProto, TValue> mapValue
)
{
// this is possible because MapField<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>
return keyValuePairs.ToDictionary(
(KeyValuePair<TKeyProto, TValueProto> kvp) => mapKey(kvp.Key),
(KeyValuePair<TKeyProto, TValueProto> kvp) => mapValue(kvp.Value));
}
For example, if you want to convert MapField<string, string> to Dictionary<Uri, int> you can use the following code:
Dictionary<Uri, int> dictionary = PToDictionary(
map,
key => new Uri(key),
val => int.Parse(val));
I have a dictionary of type
Dictionary<int, (float, float)>
when trying to read the value from it I can't use this way
if (myDict.TryGetValue(1, out (float tupleItem1, float tupleItem2))) { /* ... */ }
because then I get compile errors
The way it works is
if (myDict.TryGetValue(1, out (float, float) theTuple)) { /* ... */ }
Is there a way I can directly initialize the variables like so?
if (!myDict.TryGetValue(1, out (float tupleItem1, float tupleItem2)))
{
/* handle if not found */
tupleItem1 = 111;
tupleItem2 = -12345;
}
You can't deconstruct directly in an out parameter yet unfortunately, see this proposal.
You'll have to deconstruct it yourself:
if (!myDict.TryGetValue(1, out var result))
{
result = (111, -12345);
}
You can improve this situation slightly with an extension method:
public static class DictionaryExtensions
{
public static TValue? TryGetValue<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key) where TValue : struct
{
return dict.TryGetValue(key, out var result) ? result : null;
}
}
This lets you write:
if (myDict.TryGetValue(1) is not (float tupleItem1, float tupleItem2))
{
tupleItem1 = 111;
tupleItem2 = -12345;
}
If you find yourself doing this a lot, you could write a simple little extension method to make it more readable:
public static class DictionaryExt
{
public static TValue TryGetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TValue> getDefault)
{
return dict.TryGetValue(key, out var value)
? value
: getDefault();
}
}
Then your sample code could looks something like this:
var dict = new Dictionary<int, (float, float)>();
var result = dict.TryGetValueOrDefault(1, () => (111, -12345));
Console.WriteLine(result);
I chose to use Func<TValue> rather than TValue for the default so that you don't have to create a default value that isn't going to be used in the case that the dictionary already contains the key.
If you want a slightly simpler syntax and you don't care that the default is created for every call regardless of whether it's actually needed you could write it like this instead:
public static class DictionaryExt
{
public static TValue TryGetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultValue)
{
return dict.TryGetValue(key, out var value)
? value
: defaultValue;
}
}
Which would be called like this:
var dict = new Dictionary<int, (float, float)>();
var result = dict.TryGetValueOrDefault(1, (111, -12345));
Console.WriteLine(result);
You could of course include both methods in DictionaryExt for more flexibility.
(It's also entirely possible that the overhead of creating a Func<TValue> for every call is greater than creating a tuple for each call, so if you're worried about performance you should test it. In either case, you could pass in a precreated Func or Tuple to avoid the creation overhead.)
I am trying to create a for loop that invokes a function of several instance of class A in a dictionary, and if there is no value for a key, it creates it and then invokes it.
It seems to me as if there must be a way to create a value upon first access to a key.
I am currently using this code though I think it is not the best possible practice:
(dictionary[i] = dictionary.ContainsKey(arr[i]) ? dictionary[i] : new A()).Push(10);
Is there a cleaner for such a problem in C#?
ConcurrentDictionary has a GetOrAdd method (and other useful methods like AddOrUpdate, TryRemove etc.). If just a plain dictionary had GetOrAdd you could use that...
Luckily, you can create an extension method in a static class which you probably should name DictionaryExtensions:
public static TValue GetOrAdd<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
Func<TKey, TValue> valueFactory)
{
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
if (key == null)
throw new ArgumentNullException(nameof(key));
if (valueFactory == null)
throw new ArgumentNullException(nameof(valueFactory));
if (dictionary.TryGetValue(key, out var existingValue))
return existingValue;
var value = valueFactory(key);
dictionary.Add(key, value);
return value;
}
How to use it:
dictionary.GetOrAdd(i, () => new A()).Push(10);
This version uses a value factory so that new A() is only executed in case it is required. Another ConcurrentDictionary.GetOrAdd() overload uses a value provided as parameter which you might consider as an alternative.
I find that creating extension methods like this that closely mirrors the methods on ConcurrentDictionary is very useful.
I'd say a cleaner code would look something like this:
var key = arr[i];
var hasKey = dictionary.ContainsKey(key);
if (!hasKey)
dictionary.Add(key, new A());
var itemToUse = dictionary[key];
itemToUse.Push(10);
Although it seems to me you are looking for something shorter. I guess what you are really asking is a short-hand method that does:
Returns the value for a given key if the key exists, else adds the key to the dictionary with some default value.
I think the above code tells a lot more about the intent, but in case you want something different, I can think of following two solutions.
The first one is an extension method for getting the item:
public static TValue Get<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
var hasKey = dictionary.ContainsKey(key);
if (!hasKey)
dictionary.Add(key, defaultValue);
return dictionary[key];
}
You would use it as:
dict.Get(arr[i], defaultValue: new A())
.Push(10);
The second solution I can think of is a new derivative of Dictionary:
class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private readonly Func<TKey, TValue> _defaultValueFactory;
public DefaultDictionary(TValue defaultValue)
{
_defaultValueFactory = new Func<TKey, TValue>(x => defaultValue);
}
public DefaultDictionary(Func<TValue> defaultValueFactory)
{
_defaultValueFactory = new Func<TKey, TValue>(x => defaultValueFactory()) ?? throw new ArgumentNullException(nameof(defaultValueFactory));
}
public DefaultDictionary(Func<TKey, TValue> defaultValueFactory)
{
_defaultValueFactory = defaultValueFactory ?? throw new ArgumentNullException(nameof(defaultValueFactory));
}
public new TValue this[TKey key]
{
get
{
var hasKey = ContainsKey(key);
if (!hasKey)
{
var defaultValue = _defaultValueFactory(key);
Add(key, defaultValue);
}
return base[key];
}
set
{
base[key] = value;
}
}
}
The usage of this goes like:
var dictionary = new DefaultDictionary<string, A>(() => new A());
// ...
dictionary[arr[i]].Push(10);
I must warn you about something, this derivative of Dictionary hides the index operator. And since using IDictionary as types for members is a common practice (e.g. private IDictionary<string, A> dictionary as a member), you can't use the overloaded version without casting. So either cast your variable to DefaultDictionary every time you want to use the overloaded indexer, or have an interface for this new dictionary like:
interface IDefaultDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
new TValue this[TKey key] { get; set; }
}
And have your members, variables use it as their defining type:
private IDefaultDictionary<string, A> dictionary;
But this also means as a concrete class you must now use DefaultDictionary, and that's the trade-off.
I have a Enumerable<KeyValuePair<TKey, TValue>>. I want to create a bool TryGetValue(TKey, out TValue) extension method of it just like it is available in Dictionary<TKey, TValue>.
I tried
public static bool TryGetValue<TKey, TValue>
(this Enumerable<KeyValuePair<TKey, TValue>> mapping, TKey key, out TValue value)
{
bool retVal = false;
KeyValuePair<TKey, TValue> kvp;
kvp = mapping.First(x => x.Key.Equals(key));
if(kvp.Key == null && kvp.Value == null)
{
retVal = false;
value = default(TValue);
}
else
{
retVal = true;
value = kvp.Value;
}
return retval;
}
Is this correct way? If not please suggest one.
Note:
I cannot use a Dictionary because Keys are repeated. Moreover it will only return the first matching value?
What happens to the rest?
We can leave them. I am sending KeyValuePair created from a DataTable. I am creating that DataTable using order by columnname in its query.
Why not just use a simple foreach loop?
Example:
public static bool TryGetValue<TKey, TValue>
(this KeyValuePair<TKey, TValue>[] mapping, TKey key, out TValue value)
{
foreach(var kvp in mapping)
if (kvp.Key.Equals(key))
{
value = kvp.Value;
return true;
}
value = default(TValue);
return false;
}
Your implementation will throw an exception if the key doesn't exists due to .First(), and FirstOrDefault() would be ugly since KeyValuePair is a struct and hence you can't just compare it to null.
Sidenote:
Instead of extending KeyValuePair<TKey, TValue>[], you probably want to use IEnumerable<KeyValuePair<TKey, TValue>> instead to be more flexible.
Is there a method or technique that allows you to insert an element into a
Dictionary<TKey, TValue> guaranteeing that the item is in the first index of that dictionary's KeyCollection.
For example:
Dictionary<String, String> dic = foo.GetOutput();
// `dic` is something like:
// {"foo", "baa"},
// {"a", "b"}
I need something like:
dic.Add("key", "value", 0);
// where `0` is the index that `key` to be inserted.
foreach(KeyValuePair<String, String> key in dic)
{
Console.WriteLine("{0} = {1}", key.Key, key.Value);
}
Output:
key = value
foo = baa
a = b
By not using a dictionary.
Dictionary<TKey, TValue> is implemented as a hash-table. The position of keys internal to the dictionary depends upon the hash-code, the means by which that hash-code was reduced further to provide an index into its internal structure, and the order of insertion in an entirely implementation-dependant way.
This isn't the only way to implement a dictionary. SortedDictionary<TKey, TValue> uses a tree structure internally and so always keeps keys in an order. In this case we still can't insert something in the beginning, rather we insert something and it gets put in the appropriate place.
If ordering is what you care about most, then you don't want a puredictionary at all. Rather you want either a List<KeyValuePair<TKey, TValue>> or you want a structure that offers both the functionality of a list and of a dictionary, which is provided by OrderedDictionary. This isn't generic, but you can easily create a generic wrapper around it (doesn't give the performance benefits of internally using generics, but does give type-safety in use).
I know it is a three years old question. But found a workaround of this problem. It may help someone
Dictionary<String, String> dic = foo.GetOutput();
dic = (new Dictionary<string, string> {{"key","value"}}).Concat(dic).ToDictionary(k => k.Key, v => v.Value);
This will insert the element in the beginning of dictionary :)
Dictionaries are unordered; elements are meant to be retrieved with a key, whose hash points to its value's location.
What you might want is a List <KeyValuePair>, whose elements can be inserted into a specific index.
List<KeyValuePair<string, string>> list = dic.ToList();
list.Insert(0, new KeyValuePair<string, string>("a", "b"));
foreach(KeyValuePair<string, string> pair in list)
Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
This is not possible with Dictionary<TKey, TValue> as it presents it's values in an unordered fashion when enumerated. There is SortedDictionary<TKey, TValue> which provides ordering but it does so by using an IComparer<TKey> against the key value directly. Here you want the key to be a String and have ordering based on an int. That is not possible with either of these types.
I think you'll need to implement a new type with these very specific semantics in them. For example.
class OrderedMap<TKey, TValue> {
private readonly Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>();
private readonly List<TKey> _list = new List<TKey>();
public void Add(TKey key, TValue value) {
if (!_map.ContainsKey(key)) {
_list.Add(key);
}
_map[key] = value;
}
public void Add(TKey key, TValue value, int index) {
if (_map.ContainsKey(key)) {
_list.Remove(key);
}
_map[key] = value;
_list.Insert(index, key);
}
public TValue GetValue(TKey key) {
return _map[key];
}
public IEnumerabe<KeyValuePair<TKey, TValue>> GetItems() {
foreach (var key in _list) {
var value = _map[key];
yield return new KeyValuePair<TKey, TValue>(key, value);
}
}
}
Note this does come with some non-trivial performance differences over a traditional Dictionary<TKey, TValue>. For example Add and Remove are slower.
Dictionary<TKey, TValue> is inherently unordered (or rather, the ordering is unpredictable and shouldn't be relied upon). If you want some sort of ordering, you need to use a different type. It's hard to recommend any particular type without knowing more about your requirements.
The Dictionary<TKey, TValue> can't be ordered.
You can try SortedDictionary<TKey, TValue> instead, but that one is ordered by the Key, not by a separate index.
The Dictionary<TKey,TValue> class does not hold items in an ordered manner, so there is no "first" item.
There is a SortedDictionary<Tkey,TValue> (.NET 4.0+), which sorts by the key, but again, this is a very vague idea of "first".
this is my solution, maybe not the best solution but it works. =)
public static ComboBox FillDropDownList(Dictionary<String, String> dictionary, ComboBox dropDown, String selecione)
{
var d = new SortedDictionary<String, String>();
d.Add("0", selecione);
foreach (KeyValuePair<string, string> pair in dictionary)
{
d.Add(pair.Key, pair.Value);
}
dropDown.DataSource = new BindingSource(d, null);
dropDown.DisplayMember = "Value";
dropDown.ValueMember = "Key";
dropDown.SelectedIndex = 0;
return dropDown;
}
A Dictionary is an un-ordered collection. You could try OrderedDictionary - http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx - which has an Insert() method which is what you're after.