Concat two dictionaries so that original's shared keys are updated - c#

Say I have two dictionaries:
Dictionary<string, string> orig = new Dictionary <string, string>();
orig.Add("one", "value one");
orig.Add("two", "");
orig.Add("three", "");
Dictionary<string, string> newDict = new Dictionary <string, string>();
newDict.Add("one", "this value should not be added");
newDict.Add("two", "value two");
newDict.Add("three", "value three");
How can I merge the two dictionaries so that the resulting dictionary updates the keys only where their corresponding values are empty? Additionally, the merge should not add any keys that are present in new but not in orig. That is, "one" still has the value "value one" while "two" and "three" are updated with the values from new.
I tried using orig.Concat(new);, but that leaves me with the original dictionary. Perhaps this can be done with LINQ?

Try:
orig = orig.Keys.ToDictionary(c => c, c=>(orig[c] == "" ? newDict[c] : orig[c]));

This loop does what you want efficiently and readable:
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (var keyVal in orig)
{
if (!string.IsNullOrEmpty(keyVal.Value))
result.Add(keyVal.Key, keyVal.Value);
else
{
string val2;
if (newDict.TryGetValue(keyVal.Key, out val2))
result.Add(keyVal.Key, val2);
else
result.Add(keyVal.Key, "");
}
}
Result:
one, value one
two, value two
three, value three

I would use the foreach
foreach (var pair in orig.Where(x=> string.IsNullOrEmpty(x.Value)).ToArray())
{
orig[pair.Key] = newone[pair.Key];
}

Extension method 'one-liners' are great when they help to clarify intention, but for something like this, I would be inclined to write a small method with an explicit loop that does the desired operation. I think this is much cleaner than creating a new dictionary using various extension method transformations:
public void PopulateMissingValues(Dictionary<string, string> orig, Dictionary<string, string> newDict)
{
foreach (var pair in orig.Where(p => p.Value == string.Empty))
{
string newValue;
if (newDict.TryGetValue(pair.Key, out newValue))
orig[pair.Key] = newValue;
}
}

Related

Is it possible to store a KeyValuePair of a dictionary without the use of a foreach loop?

The syntax for iterating over a dictionary with a foreach loop is:
foreach (KeyValuePair<key, value> item in dictionary)
Inside the foreach loop the key is accessed with item.key and the value with item.value.
This got me thinking, can this be used without the use of a foreach loop as a convenient (although niche) way to represent a specific dictionary pair?
I am not looking for some weird work arounds, like running a foreach loop and saving the KeyValuePair into a variable once the target key is reached, because at this point it would be more convenient to just use 2 variables.
Like this
var dic = new Dictionary<string, int>();
dic["a"] = 42;
KeyValuePair<string, int> keyVal;
foreach(var kv in dic) {
keyVal = kv; << gets the last entry from the dictioanry
}
Note that the dictionary does not store KeyValuePairs, it creates one for the enumeration, so the simple thing to do is this (because we are not expensively recreating something)
var dic = new Dictionary<string, int>();
dic["a"] = 42;
KeyValuePair<string, int> keyVal = new KeyValuePair<string, int>("a", dic["a"]);
this is more efficient than the (neat) LINQ Sinlge method
The IDictionary<TKey, TValue> interface implements IEnumerable<KeyValuePair<TKey,TValue>>. This means you can simply use Single() to get the entry you want.
IDictionary<string, int> dict = ...;
KeyValuePair<string, int> entry = dict.Single(it => it.Key == "yourKey");
try this
var dict = new Dictionary<string, string>() {
{"hi","Hello World!"},
{"adieu","Goodby"}
};
string hi = dict["hi"]; //Hello World!
or if you want a list
List<KeyValuePair<string,string>> list = dict.ToList();
result
[{"Key":"hi","Value":"Hello World!"},{"Key":"adieu","Value":"Goodby"}]

Removing specific entries(defined in a List<string>) from Dictionary<string, int> gives critical error -->

I have a List collection of strings. Like so,
public List<string> filterWords = new List<string>()
{
"an" ,
"be",
" ",
"in",
"the",
"of"
..
...
.
.
....
};
I have a dictionary collection in format of Dictionary<string, int>, Like so,
{{of, 2}},
{{an, 4}},
{{in, 7}},
{{the, 8}},
{{literate, 3}},
{{culture, 5}},
{{be, 5}},
...
and so and so
Aim is to check/find out and remove from the above dictionary entries that contain keys from the previous list. ie an, be etcetc.
Basic code I have put together so far is --
public Dictionary<string, int> UniqueWordsDictionary(Dictionary<string, int> inputDict)
{
try
{
FilterWords flObj = new FilterWords();
var dictionary = new Dictionary<string, int>();
int idx = 0;
var wordsToRemove = flObj.filterWords
.Select(record => record.Substring(0, record.IndexOf(',')));
foreach(string wrd in wordsToRemove)
{
inputDict.Remove(wrd);
}
dictionary = inputDict;
return dictionary;
}
catch(Exception exp)
{
throw exp.GetBaseException();
}
}
The logic probably wrong. Exception I am getting
An item with the same key has already been added.
The stack trace -
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) at ....
idx=0 been used, because I simply need a default value of 0 in the values of the dictionary. Logic seemed ok. What's a very sharp, precise solution for this. Any critical lambda expression that can do the needful? What is wrong with the foreach on 'wordsToRemove' ?
Observe my posted code block. There's a commented line dictionary=wordsToRemove.Select .............
I tried alternatively commenting in that one and the foreach loop dictionary.Add. Error is same in both cases.
** read comments added to code block closely
Thx.
If you want to remove, let's Remove:
List<string> filterWords = ...
// I have a dictionary collection in format of Dictionary<string, int>, Like so
Dictionary<string, int> dictionary = ...
...
// then we Remove each word in wordsToRemove from dictionary
foreach (string word in filterWords)
dictionary.Remove(word);

How to compare two dictionaries in C#?

There are different count and different order of dictionaries
If the key of list A and list B match, I would like to bring the value of list B and modify the value of list A.
Sample Code :
public static List<Dictionary<string, string>> ListDicOne = new List<Dictionary<string, string>>();
public static List<Dictionary<string, string>> ListDicTwo = new List<Dictionary<string, string>>();
(...)
ListDicOne[0].Add("ABCD", ""); // empty value
ListDicOne[1].Add("ABCD", "");
ListDicOne[2].Add("EFGH", "test");
ListDicTwo[0].Add("AABC", "oooo");
ListDicTwo[1].Add("ABCD", "WOW");
ListDicTwo[2].Add("CCDD", "haha");
ListDicTwo[3].Add("CCDD", "haha");
expected result value :
// Console Write key and value of ListDicA
ABCD \t WOW
ABCD \t WOW
EFGH \t test
I will take a guess and assume you really only want to deal with two dictionaries, and not two lists of many one-item dictionaries, which would not make any sense at all.
First, the dictionaries should be declared like this (I also assume they don't have to be public):
private static Dictionary<string, string> ListDicOne = new Dictionary<string, string>();
private static Dictionary<string, string> ListDicTwo = new Dictionary<string, string>();
And then, the usage could be like this:
ListDicOne.Add("AABC", ""); // I changed the key, they must be unique
ListDicOne.Add("ABCD", "");
ListDicOne.Add("EFGH", "test");
ListDicTwo.Add("AABC", "oooo");
ListDicTwo.Add("ABCD", "WOW");
ListDicTwo.Add("CCDD", "haha");
ListDicTwo.Add("CCDE", "haha"); // I changed the key, they must be unique
foreach (var item in ListDicTwo)
{
if (ListDicOne.ContainsKey(item.Key))
ListDicOne[item.Key] = ListDicTwo[item.Key];
}
The final state of ListDicOne is:
("AABC", "oooo")
("ABCD", "WOW")
("EFGH", "test")
I hope you find this clarifying and useful.
** Update **
Considering a string-string list with non-unique keys:
private static List<Tuple<string, string>> ListOne = new List<Tuple<string, string>>();
private static List<Tuple<string, string>> ListTwo = new List<Tuple<string, string>>();
(...)
ListOne.Add(Tuple.Create("ABCD", ""));
ListOne.Add(Tuple.Create("ABCD", ""));
ListOne.Add(Tuple.Create("EFGH", "test"));
ListTwo.Add(Tuple.Create("AABC", "oooo"));
ListTwo.Add(Tuple.Create("ABCD", "WOW"));
ListTwo.Add(Tuple.Create("CCDD", "haha"));
ListTwo.Add(Tuple.Create("CCDD", "haha"));
foreach (var l2item in ListTwo)
{
for (int i = 0; i < ListOne.Count; i++)
{
if (ListOne[i].Item1 == l2item.Item1)
ListOne[i] = Tuple.Create(l2item.Item1, l2item.Item2);
}
}
Note 1: tuples are immutable, so you need to create a new one when changing Item2.
Note 2: You cannot use foreach when you need to alter the iterated list, therefore I used a for instead.
Note 3: If ListTwo happens to have a two different key-value combinations (supposedly won't happen), the second one will overwrite the first.
This is the end result with your test values:
("ABCD", "WOW")
("ABCD", "WOW")
("EFGH", "test")

Get Values from dictionary present in List

I have a list like,
List<string> list = new List<string>();
list.Add("MEASUREMENT");
list.Add("TEST");
I have a dictionary like,
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("BPGA", "TEST");
dict.Add("PPPP", "TEST");
dict.Add("RM_1000", "MEASUREMENT");
dict.Add("RM_2000", "MEASUREMENT");
dict.Add("CDMA", "TEST");
dict.Add("X100", "XXX");
Now, I want to get all matched data from dictionary based on list.
Means, all data from list match with dict value then get new dictionary with following mathched values
Is there any way to achieve this by using lambda expression?
I want result like this.
Key Value
"BPGA", "TEST"
"PPPP", "TEST"
"RM_1000", "MEASUREMENT"
"RM_2000", "MEASUREMENT"
"CDMA", "TEST"
Thanks in advance!
You should be using the dictionary like it is intended to be used i.e. a common key with multiple values for example:
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
Then all you need to do when adding the values is:
dict.Add("TEST", new List<string>() { /*strings go in here*/ });
Then to get all the results from a key like:
List<string> testValues = dict["TEST"];
To make it safe however you should check that the key exists i.e.
if (dict.ContainsKey("TEST"))
{
//Get the values
}
Then to add values to a current key you go do something like:
dict["TEST"].Add("NewValue");
If you insist on keeping the same structure, although I do not recommend it, something like the following will work:
List<string> testKeys = new List<string>();
foreach (var pairs in dict)
{
if (pair.Value == "TEST")
{
testKeys.Add(pair.Key);
}
}
Or even the following LINQ statement:
List<string> testKeys = dict.Where(p => p.Value == "TEST").Select(p => p.Key).ToList();
For a generic query to find the ones from your list use:
List<string> values = dict.Where(p => list.Contains(p.Value)).ToList();

Checking all entries from one Dictionary are in another Dictionary

i have two Dictionarys A & B, i want to see if all entries in A exist in B. In the past i've compared Lists using the following:
var set1 = new HashSet<String>(list1);
var set2 = new HashSet<String>(list2);
return set1.SetEquals(set2);
What i have thought to do is simply loop over each value in Dictionary A using:
dictA.TryGetValue(dictBvalue, out item)
this will return null on the item var if the value isn't there, but this seems a little long winded.
Is there a quick and effcient way of comparing dictionaries?
Thanks.
You could use All extension and do this.
var allexist = list1.All(x=> list2.ContainsKey(x.Key) && list2[x.Key] == x.Value)
here is the solution if you want to loop over each value
Dictionary<string, string> dictA = new Dictionary<string, string>();
Dictionary<string, string> dictB = new Dictionary<string, string>();
bool allexist = true;
foreach (var itemA in dictA)
{
if (!dictB.ContainsKey(itemA.Key))
{
allexist = false;
}
}
Actually, you asked for a method comparing dictionaries but your code example refer to HashSet which is different.
For HashSets, you can use IsSubsetOf and SetEquals methods.
To compare dictionaries, you can use DictionaryEquals method from this answer

Categories

Resources