How to update the value stored in Dictionary in C#? - c#

How to update value for a specific key in a dictionary Dictionary<string, int>?

Just point to the dictionary at given key and assign a new value:
myDictionary[myKey] = myNewValue;

It's possible by accessing the key as index
for example:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2

You can follow this approach:
void addOrUpdate(Dictionary<int, int> dic, int key, int newValue)
{
int val;
if (dic.TryGetValue(key, out val))
{
// yay, value exists!
dic[key] = val + newValue;
}
else
{
// darn, lets add the value
dic.Add(key, newValue);
}
}
The edge you get here is that you check and get the value of corresponding key in just 1 access to the dictionary.
If you use ContainsKey to check the existance and update the value using dic[key] = val + newValue; then you are accessing the dictionary twice.

Use LINQ: Access to dictionary for the key and change the value
Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);

This simple check will do an upsert i.e update or create.
if(!dictionary.TryAdd(key, val))
{
dictionary[key] = val;
}

Here is a way to update by an index much like foo[x] = 9 where x is a key and 9 is the value
var views = new Dictionary<string, bool>();
foreach (var g in grantMasks)
{
string m = g.ToString();
for (int i = 0; i <= m.Length; i++)
{
views[views.ElementAt(i).Key] = m[i].Equals('1') ? true : false;
}
}

update - modify existent only. To avoid side effect of indexer use:
int val;
if (dic.TryGetValue(key, out val))
{
// key exist
dic[key] = val;
}
update or (add new if value doesn't exist in dic)
dic[key] = val;
for instance:
d["Two"] = 2; // adds to dictionary because "two" not already present
d["Two"] = 22; // updates dictionary because "two" is now present

This may work for you:
Scenario 1: primitive types
string keyToMatchInDict = "x";
int newValToAdd = 1;
Dictionary<string,int> dictToUpdate = new Dictionary<string,int>{"x",1};
if(!dictToUpdate.ContainsKey(keyToMatchInDict))
dictToUpdate.Add(keyToMatchInDict ,newValToAdd );
else
dictToUpdate[keyToMatchInDict] = newValToAdd; //or you can do operations such as ...dictToUpdate[keyToMatchInDict] += newValToAdd;
Scenario 2: The approach I used for a List as Value
int keyToMatch = 1;
AnyObject objInValueListToAdd = new AnyObject("something for the Ctor")
Dictionary<int,List<AnyObject> dictToUpdate = new Dictionary<int,List<AnyObject>(); //imagine this dict got initialized before with valid Keys and Values...
if(!dictToUpdate.ContainsKey(keyToMatch))
dictToUpdate.Add(keyToMatch,new List<AnyObject>{objInValueListToAdd});
else
dictToUpdate[keyToMatch] = objInValueListToAdd;
Hope it's useful for someone in need of help.

This extension method allows a match predicate delegate as the dictionary key selector, and a separate delegate to perform the dictionary value replacement, so it's completely open as to the type of key/value pair being used:
public static void UpdateAll<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<TKey, TValue, bool> matchPredicate, Func<TValue, TValue> updatePredicate)
{
var keys = dictionary.Keys.Where(k => matchPredicate(k, dictionary[k])).ToList();
foreach (var key in keys)
{
dictionary[key] = updatePredicate(dictionary[key]);
}
}
Example usage:
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "One");
dict.Add(2, "Two");
dict.Add(3, "Three");
//Before
foreach(var kvp in dict){
Console.WriteLine(kvp.Value);
}
dict.UpdateAll(
matchPredicate: (k, v) => k >= 2, //Update any dictionary value where the key is >= 2
updatePredicate: (v) => v = v + " is greater than One"
);
//After
foreach(var kvp in dict){
Console.WriteLine(kvp.Value);
}

You Can Also Use This Method :
Dictionary<int,int> myDic = new();
if (myDic.ContainsKey(1))
{
myDic[1] = 1234; // or use += to update it
}
Or By Value :
if (myDic.ContainsValue(1))
{
//do something ...
}

Related

IDictionary<String, List<OpenXmlCompositeElement>> - get the List<OpenXmlCompositeElement>?

I'm working with Open XML & I have a IDictionary<String, List<OpenXmlCompositeElement>> structure. I want to work with the List part of the structure but this.map.Values tries to wrap it in an ICollection. How can I get the List part from my structure?
public List<OpenXmlCompositeElement> MapData()
{
//this does not work
return this.map.Values;
}
Since it is a dictionary, it expects you to tell from which key you want the value.
So this would be the code you need, where yourKey is the key you want to retrieve:
public List<OpenXmlCompositeElement> MapData()
{
return this.map["yourKey"];
}
If you have no interest in the key, and the dictionary is just a dictionary because the serializer says so, you could get the first item for example like this:
public List<OpenXmlCompositeElement> MapData()
{
return this.map.Values.First();
}
You can either loop through the dictionary and use the value you would like, or access the List directly using the key (in this case it's a string)
IDictionary<String, List<OpenXmlCompositeElement>> myDictionary;
List<OpenXmlCompositeElement> myList = myDictionary["myKey"];
Where myKey is available in the dictionary.
Alternatively you can loop through
foreach (var item in myDictionary)
{
var key = item.Key;
var value = item.Value
// You could then use `key` if you are unsure of what
// items are in the dictionary
}
Assuming this is your dictionary...
IDictionary<string, List<OpenXmlCompositeElement>> items = ...;
Get a specific List by key...
List<OpenXmlCompositeElement> list = items["key"];
Get the first list in the dictionary...
List<OpenXmlCompositeElement> list = items.Values.First();
Concatenate all lists in the dictionary into a single list...
List<OpenXmlCompositeElement> list = items.SelectMany(o => o).ToList();
foreach(KeyValuePair<string, List<OpenXmlCompositeElement>> kvp in IDictionary)
{
string key = kvp.key
List<OpenXmlCompositeElement> list = kvp.Value;
foreach(OpenXmlCompositeElement o in list)
{
Do anything you need to your List here
}
}
I am working with dictionaries as well, so here is a real example that I am currently working with:
foreach(KeyValuePair<string, List<DataRecords>> kvp in vSummaryResults)
{
string sKey = kvp.Key;
List<DataRecords> list = kvp.Value;
string[] vArr = sKey.Split(',');
int iTotalTradedQuant = 0;
double dAvgPrice = 0;
double dSumQuantPrice = 0;
double dQuantPrice = 0;
double dNumClose = 0;
foreach (DataRecords rec in list)
{
if(vSummaryResults.ContainsKey(sKey))
{
iTotalTradedQuant += rec.iQuantity;
dQuantPrice = rec.iQuantity * rec.dInputTradePrice;
dSumQuantPrice += dQuantPrice;
dAvgPrice = dSumQuantPrice / iTotalTradedQuant;
dNumClose = rec.dNumericClosingPrice;
}
else
{
vSummaryResults.Add(sKey, list);
//dNumClose = rec.dNumericClosingPrice;
}

How to compare key/value dictionary with == operator on a IReadOnlyCollection<string>?

I have a MultiValueDictionary<string, string> where I am trying to get a key by value.
var dic = na.prevNext; // Getter to get MultiValueDictionary
string nodePointingToThisOne = "";
foreach (var item in dic)
{
if(item.Value == "test")
{
nodePointingToThisOne = item.Key;
}
break;
}
This does not work so I tried Linq:
string nodePointingToThisOne = dic.Where(x => x.Value == this.nodeID).Select(x => x.Key);
But on both I get this error: Operator '==' cannot be applied to operands of type 'System.Collections.Generic.IReadOnlyCollection<string>' and 'string'
So my question is how do I make this comparison work for a read-only collection? I am aware that I get problems if a key exists multiple times but I reduced the problem to this one for now.
I read
Get Dictionary key by using the dictionary value
LINQ: Getting Keys for a given list of Values from Dictionary and vice versa
get dictionary key by value
Getting key of value of a generic Dictionary?
Get key from value - Dictionary<string, List<string>>
but they deal with a "normal" dictionary.
Since the Value property it self may contain multiple values you can't compare it directly against certain string using == operator. Use Contains() instead :
.....
if (item.Value.Contains("test"))
{
.....
}
...or in method chain version :
string nodePointingToThisOne = dic.Where(x => x.Value.Contains("test"))
.Select(x => x.Key)
.FirstOrDefault();
Try to iterate by Keys and then compare the value, and return the Key only if the Value matches.
Like this:
foreach (var key in dic.Keys)
{
if(dic[key].Contains("your value"))
return key;
}
You can iterate over keys like this
foreach (var key in dic.Keys)
{
if(key == "your key")
return key;
}
You can also iterate over values like this
foreach (var v in dic.Values)
{
if(v == "your value")
return v;
}
Example:
Dictionary<string, string> c = new Dictionary<string, string>();
c.Add("Pk", "Pakistan");
c.Add("Aus", "Australia");
c.Add("Ind", "India");
c.Add("Nz", "New Zeland");
c.Add("SA", "South Africa");
foreach (var v in c.Values)
{
if (v == "Australia")
{
Console.WriteLine("Your Value is = " + v);
// perform your task
}
}
foreach (var k in c.Keys)
{
if (k == "Aus")
{
// perform your task
Console.WriteLine("Your Key is = " + k);
}
}
Output:
Your Value is = "Australia"
Your Key is = "Aus"
If you look at the MultiValueDictionary, line 81 will give you a hint. It is:
[TestInitialize]
public void TestInitialize()
{
MultiValueDictionary = new MultiValueDictionary<TestKey, string>();
}
protected static void AssertAreEqual( IDictionary<TestKey, string[]> expected,
IMultiValueDictionary<TestKey, string> actual )
{
Assert.AreEqual( expected.Count, actual.Count );
foreach ( var k in expected.Keys )
{
var expectedValues = expected[ k ];
var actualValues = actual[ k ];
AssertAreEqual( expectedValues, actualValues );
}
}
So for your case, the solution is similar:
foreach (var item in dic.keys)
{
if(dict[item] == "test")
{
nodePointingToThisOne = item;
return nodePointingToThisOne;
}
}
worked for me:
foreach (int i in Dictionary.Keys)
{
if (Dictionary.Values.ToString() == "Your Value")
{
return Dictionary.Keys;
}
}

Updating a dictionary dynamically with foreach

When trying to update a Dictionary with the following:
foreach(KeyValuePair<string, string> pair in dict)
{
dict[pair.Key] = "Hello";
}
And exception is thrown. Is there any way to dynamically update the dictionary WITHOUT making any kind of key or value backups?
EDIT!!!!!! View code. I realized that this portion was actually doable. The real case is this. I thought they would be the same, but they are not.
foreach(KeyValuePair<string, string> pair in dict)
{
dict[pair.Key] = pair.Key + dict[pair.Key];
}
Any reason why you're not iterating over the keys?
foreach(var key in dict.Keys)
{
dict[key] = "Hello";
}
You can either loop over the dictionary (you need to use ToList because you can't change a collection that is being looped over in a foreach loop)
foreach(var key in dict.Keys.ToList())
{
dict[key] = "Hello";
}
or you can do it in one line of LINQ as you're setting the same value to all the keys.
dict = dict.ToDictionary(x => x.Key, x => "Hello");
Updated question
foreach (var key in dict.Keys.ToList())
{
dict[key] = key + dict[key];
}
and the LINQ version
dict = dict.ToDictionary(x => x.Key, x => x.Key + x.Value);
If you want to avoid using ToList, you can use ElementAt so that you can modify the collection directly.
for (int i = 0; i < dict.Count; i++)
{
var item = dict.ElementAt(i);
dict[item.Key] = item.Key + item.Value;
}

How to randomly remove a key from dictionary based on value?

How can I randomly remove a key with value 0 efficiently ?
Dictionary<string, int> dict = new Dictionary<Edge, int>();
dict.add("a",0);
dict.add("b",0);
dict.add("c",0);
dict.add("d",1);
The size of dictionary is 10000.
Something like this should do it:
IEnumerable<string, int> pairsToRemove = dictionary.Where(pair => pair.Value == 0);
To generate a random index, you could use:
int indexToRemove = [RandomNumber] % pairsToRemove.Length() -1;
Find the indexToRemove th element from pairsToRemove and remove it from the dictionary.
As to efficiency:
The complexity should be O(n)[get all items with value 0] + O(.6N)[finding ith value to remove] + O(log(n))[deletion] assuming the random number generation is constant time.
The problem is, there is no way to perform a value lookup on a dictionary in better than O(n) time. So that will be your bottleneck.
This will remove the first item with a zero value. It's not precisely "random", but is non-deterministic.
Dictionary<string, int> dict = new Dictionary<string, int>();
string keyToRemove = null;
foreach (var kvp in dict)
{
if (kvp.Value == 0)
{
keyToRemove = kvp.Key;
break;
}
}
if (keyToRemove != null)
{
dict.Remove(keyToRemove);
}

Mapping from 2D array in C#

I want to use a 2-D array in C#, e.g:
string[,] a = new string[,]
{
{"aunt", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
My requirement is that when I pass "aunt" to this array I want to get corresponding AUNT_ID from the 2-D array.
As others have said, a Dictionary<string, string> would be better - and you can use a collection initializer to create it simply:
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{"ant", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
If you're confident that your key is in the dictionary, and you're happy for an exception to be thrown otherwise:
string value = dictionary[key];
or if it might not be:
string value;
if (dictionary.TryGetValue(key, out value))
{
// Use value here
}
else
{
// Key wasn't in dictionary
}
If you really need to use an array, if you can change it to a multidimensional array (string[][]), you can use:
// Will throw if there are no matches
var value = array.First(x => x[0] == key)[1];
Or again to be more circumspect:
var pair = array.FirstOrDefault(x => x[0] == key);
if (pair != null)
{
string value = pair[1];
// Use value here
}
else
{
// Key wasn't in dictionary
}
LINQ unfortunately doesn't work quite as well on rectangular arrays. It probably wouldn't be too hard to write a method to allow it to be treated "somewhat" like an array of arrays, admittedly...
Use Dictionary<string, string> for that:
Dictionary<string, string> arr = new Dictionary<string, string>();
arr.Add("ant", "AUNT_ID");
arr.Add("Sam", "AUNT_NAME");
arr.Add("clozapine", "OPTION");
string k = arr["ant"]; // "AUNT_ID"
The best option for you is to use Dictionary, but if you still wants to use 2D array, you may try the following
string[,] a = new string[,]
{
{"ant", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
string search = "ant";
string result = String.Empty;
for (int i = 0; i < a.GetLength(0); i++) //loop until the row limit
{
if (a[i, 0] == search)
{
result = a[i, 1];
break; //break the loop on find
}
}
Console.WriteLine(result); // this will display AUNT_ID
It looks rather like you want a dictionary:
Dictionary<string, string> a = new Dictionary<string, string>();
a.Add("ant", "AUNT_ID");
a.Add("Sam", "AUNT_NAME");
a.Add("clozapine", "OPTION");
string s = a["ant"]; // gets "AUNT_ID"
To check if a key exists in the dictionary:
if (a.ContainsKey("ant")) {
...
}
Or:
string s;
if (a.TryGetValue("ant", out s)) {
...
}
for (i=0; i<3; i++){
if (!String.Compare(a[i][0], string)){
stored_string= a[i][1];
}
}

Categories