C#: Remove duplicate values from dictionary? - c#

How can I create a dictionary with no duplicate values from a dictionary that may have duplicate values?
IDictionary<string, string> myDict = new Dictionary<string, string>();
myDict.Add("1", "blue");
myDict.Add("2", "blue");
myDict.Add("3", "red");
myDict.Add("4", "green");
uniqueValueDict = myDict.???
Edit:
-I don't care which key is kept.
- Is there something using Distinct() operation?

What do you want to do with the duplicates? If you don't mind which key you lose, just build another dictionary like this:
IDictionary<string, string> myDict = new Dictionary<string, string>();
myDict.Add("1", "blue");
myDict.Add("2", "blue");
myDict.Add("3", "red");
myDict.Add("4", "green");
HashSet<string> knownValues = new HashSet<string>();
Dictionary<string, string> uniqueValues = new Dictionary<string, string>();
foreach (var pair in myDict)
{
if (knownValues.Add(pair.Value))
{
uniqueValues.Add(pair.Key, pair.Value);
}
}
That assumes you're using .NET 3.5, admittedly. Let me know if you need a .NET 2.0 solution.
Here's a LINQ-based solution which I find pleasantly compact...
var uniqueValues = myDict.GroupBy(pair => pair.Value)
.Select(group => group.First())
.ToDictionary(pair => pair.Key, pair => pair.Value);

The brute-force solution would be something like the following
var result = dictionary
.GroupBy(kvp => kvp.Value)
.ToDictionary(grp => grp.First().Value, grp.Key)
assuming you don't really care about the key used to represent a group of duplicates and it is acceptable to rebuild the dictionary.

Jon beat me to the .NET 3.5 solution, but this should work if you need a .NET 2.0 solution:
List<string> vals = new List<string>();
Dictionary<string, string> newDict = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> item in myDict)
{
if (!vals.Contains(item.Value))
{
newDict.Add(item.Key, item.Value);
vals.Add(item.Value);
}
}

foreach (var key in mydict.Keys)
tempdict[mydict[key]] = key;
foreach (var value in tempdict.Keys)
uniquedict[tempdict[value]] = value;

Dictionary<string, string> test = new Dictionary<string,string>();
test.Add("1", "blue");
test.Add("2", "blue");
test.Add("3", "green");
test.Add("4", "red");
Dictionary<string, string> test2 = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> entry in test)
{
if (!test2.ContainsValue(entry.Value))
test2.Add(entry.Key, entry.Value);
}

This is how I did it:
dictionary.add(control, "string1");
dictionary.add(control, "string1");
dictionary.add(control, "string2");
int x = 0;
for (int i = 0; i < dictionary.Count; i++)
{
if (dictionary.ElementAt(i).Value == valu)
{
x++;
}
if (x > 1)
{
dictionary.Remove(control);
}
}

In addition to the answer of Jon Skeet , if your value is an intern object you can use :
var uniqueValues = myDict.GroupBy(pair => pair.Value.Property)
.Select(group => group.First())
.ToDictionary(pair => pair.Key, pair => pair.Value);
This way you will remove the duplicate only on one property of the object

Just a footnote to those using the Revit API, this is one method that works for me in removing duplicate elements, when you can't use say wallType as your object type and instead need to leverage raw elements. it's a beaut mate.
//Add Pair.value to known values HashSet
HashSet<string> knownValues = new HashSet<string>();
Dictionary<Wall, string> uniqueValues = new Dictionary<Wall, string>();
foreach (var pair in wall_Dict)
{
if (knownValues.Add(pair.Value))
{
uniqueValues.Add(pair.Key, pair.Value);
}
}

Related

Loop through multiple dictionaries

I have 6 dictionaries. I want to compare another dictionaries against each one of them and see what dictionaries contains what strings. Is it possible to do with a foreach loop?
static Dictionary<string, int> d = new Dictionary<string, int>();
static Dictionary<string, double> dNL = new Dictionary<string, double>();
static Dictionary<string, double> dDE = new Dictionary<string, double>();
static Dictionary<string, double> dFR = new Dictionary<string, double>();
static Dictionary<string, double> dSP = new Dictionary<string, double>();
static Dictionary<string, double> dEN = new Dictionary<string, double>();
static Dictionary<string, double> dIT = new Dictionary<string, double>();
foreach (var f in d)
{
if (dNL.ContainsKey(f.Key))
{
//add to a numeric?
}
if (dDE.ContainsKey(f.Key))
{
//add to a numeric?
}
}
something like this?
what I currently have (and not working like intended):
// need to find a better solution
foreach (var f in d)
{
if (dNL.ContainsKey(f.Key))
{
dNLtotaal++;
}
}
foreach (var f in d)
{
if (dDE.ContainsKey(f.Key))
{
dDEtotaal++;
}
}
foreach (var f in d)
{
if (dFR.ContainsKey(f.Key))
{
dFRtotaal++;
}
}
foreach (var f in d)
{
if (dSP.ContainsKey(f.Key))
{
dSPtotaal++;
}
}
foreach (var f in d)
{
if (dEN.ContainsKey(f.Key))
{
dENtotaal++;
}
}
foreach (var f in d)
{
if (dIT.ContainsKey(f.Key))
{
dITtotaal++;
}
}
// NEED A MUCH BETTER SOLUTION
List<int> totaleD = new List<int>();
totaleD.Add(dNLtotaal);
totaleD.Add(dDEtotaal);
totaleD.Add(dFRtotaal);
totaleD.Add(dSPtotaal);
totaleD.Add(dENtotaal);
totaleD.Add(dITtotaal);
int max = !totaleD.Any() ? -1 : totaleD.Select((value, index) => new { Value = value, Index = index }).Aggregate((a, b) => (a.Value > b.Value) ? a : b).Index;
var maxIndex = totaleD.IndexOf(totaleD.Max());
Console.WriteLine(maxIndex);
You can do something like this:
var items = d.Keys;
var dictionaries = new[] { dNL, dDE, dFR, dSP, dEN, dIT };
var result = dictionaries.Select((d, index) =>
new {
Index = index,
Matches = items.Count(i => d.ContainsKey(i))
})
.OrderByDescending(i => i.Matches)
.Select(i => i.Index)
.FirstOrDefault();
Which gives you the index of the dictionary with the most matches
You could use lambda expressions to get the desired results. In following example, I tried to use two dictionaries:
int dNLtotaal = 0;
Dictionary<string, double> dNL = new Dictionary<string, double>();
Dictionary<string, double> dDE = new Dictionary<string, double>();
dNL.Keys.Where(k => dDE.ContainsKey(k)).ToList().ForEach(k => dNLtotaal++);
Hope it helps
Why not to have 1 Dictionary instead of 6? And keep there a pair [string, List[SomeObject]] where SomeObject is a class like
class SomeObject
{
public Enum Type;//dNL, dDE etc
public double Value;
}

How to retrieve all values in dictionary

I have the following Dictionary
public static Dictionary<string, List<int>> termDocumentIncidenceMatrix = new Dictionary<string, List<int>>();
I want to print all values in it , How i can make it ?
I found KeyValuePair but can't recognize in my program ?
Can anyone give me bit of code or link ?
foreach (var term in termDocumentIncidenceMatrix)
{
// Print the string (your key)
Console.WriteLine(term.Key);
// Print each int in the value
foreach (var i in term.Value)
{
Console.WriteLine(i);
}
}
If you want to print all values of the dictionary, you can use:
Dictionary<string, List<int>> dict = new Dictionary<string,List<int>>{{"A",new List<int>{1,2}},{"B",new List<int>{3,4}}};
var integersList = dict.Values.SelectMany(it => it);
foreach (var item in integersList)
{
Console.WriteLine(item);
}

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