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

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);
}

Related

How to convert dictionary keys to array of strings (insert at array index as specified in dictionary.value)

Dictionary<String, UInt32> dict = new Dictionary<String, UInt32>();
dict.Add("1", 1);
dict.Add("4", 4);
dict.Add("5", 5);
Quick way to convert all keys to array is
string[] keys = dict.Keys.ToArray();
This is how memory representation of array would look
keys[0] = "1" keys[1] = "4" keys[2] = "5"
What I want is, key string value should be in array at the index specified by value.
keys[1] = "1" keys[4] = "4" keys[5] = "5"
This is what I tried, it works..
Int32 count = -1;
foreach (KeyValuePair<String, UInt32> kvp in dict)
{
if (kvp.Value > count)
{
count = (Int32)kvp.Value;
}
}
String[] labelarray = new String[count + 1];
foreach (KeyValuePair<String, UInt32> kvp in dict)
{
labelarray[kvp.Value] = kvp.Key;
}
But Is there any better, cleaner way to do above?
You can use Enumerable.ToDictionary to revert keys and values.
var revertedDictionary = list.ToDictionary(x => x.Value, x => x.Key);
Another way with List<T> or Array has 2 parts: searching max index and filling collection:
if(!list.Any())
{
// use different behavior if you need
return new string[0];
}
var maxValue = list.Values.Max();
var newList = new string[maxValue];
Enumerable
.Range(0, (int)maxValue)
.ToList()
.ForEach(x => newList[x] = list.ContainsValue((uint)x) ? x.ToString() : string.Empty);
// improve memory usage by preventing to create new List in ToList() method
foreach(var index in Enumerable.Range(0, (int)maxValue))
{
newList[index] = list.ContainsValue((uint)index) ? index.ToString() : string.Empty;
}

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;
}

using a for loop to iterate through a dictionary

I generally use a foreach loop to iterate through Dictionary.
Dictionary<string, string> dictSummary = new Dictionary<string, string>();
In this case I want to trim the entries of white space and the foreach loop does however not allow for this.
foreach (var kvp in dictSummary)
{
kvp.Value = kvp.Value.Trim();
}
How can I do this with a for loop?
for (int i = dictSummary.Count - 1; i >= 0; i--)
{
}
what about this?
for (int i = dictSummary.Count - 1; i >= 0; i--) {
var item = dictSummary.ElementAt(i);
var itemKey = item.Key;
var itemValue = item.Value;
}
KeyValuePair<TKey, TValue> doesn't allow you to set the Value, it is immutable.
You will have to do it like this:
foreach(var kvp in dictSummary.ToArray())
dictSummary[kvp.Key] = kvp.Value.Trim();
The important part here is the ToArray. That will copy the Dictionary into an array, so changing the dictionary inside the foreach will not throw an InvalidOperationException.
An alternative approach would use LINQ's ToDictionary method:
dictSummary = dictSummary.ToDictionary(x => x.Key, x => x.Value.Trim());
You don't need to use .ToArray() or .ElementAt(). It is as simple as accessing the dictionary with the key:
dictSummary.Keys.ToList().ForEach(k => dictSummary[k] = dictSummary[k].Trim());

How to Compare Values of Two Dictionary and Increment Count if DictA key,values Exists in DictB?

I have Two Dictionary DictA & DictB such as:
Dictionary<int, string> DictA = new Dictionary<int, string>();
DicA.add(1,"Mango");
DicA.add(2,"Grapes");
DicA.add(3,"Orange");
Dictionary<int, string> DictB = new Dictionary<int, string>();
DicB.add(1,"Mango");
DicB.add(2,"Pineapple");
How to Compare the values of these Two Dictionary DictA key,value with DictB key,value and if MATCH IS FOUND then INCREMENT the COUNTER variable.
Note: DicA may Contains many Rows as compared to DicB
EG: DicA has 3 Rows and DicB has 2 Rows. If DicA key,value match(similar/equal) to DicB key,val then increment the counter variable by one!
Any Suggestion..! Help Appreciated...!
Use this code:
int matches = DictA.Keys.Where(k => DictB.ContainsKey(k) && DictB[k] == DictA[k]).Count();
You could use:
Dictionary<int, string> DicA = new Dictionary<int, string>();
DicA.Add(1,"Mango");
DicA.Add(2,"Grapes");
DicA.Add(3,"Orange");
Dictionary<int, string> DicB = new Dictionary<int, string>();
DicB.Add(1,"Mango");
DicB.Add(2,"Pineapple");
int counter = 0;
foreach (var pair in DicA)
{
string value;
if (DicB.TryGetValue(pair.Key, out value))
{
if (value == pair.Value)
{
counter++;
}
}
}

How to update the value stored in Dictionary in 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 ...
}

Categories