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")
Related
Hello I try to do something like PHP thing that is retrieve data from database and store in 2 dimension collection (Dictionary)
I'm not sure I write it correctly or not.
Let's say my database table and expected structure result look like this (See the screenshot)
Click to see screenshot
public ActionResult ShowBook()
{
var books = from v in db.Books
select v;
Dictionary<string, Dictionary<string, string>> test = new Dictionary<string, Dictionary<string, string>>();
foreach (var item in books)
{
test[item.Book_Type_ID][item.Author_ID] = item.Book_Name;
}
return .....
}
But I has this error
System.Collections.Generic.KeyNotFoundException: 'The given key was not present in the dictionary.'
How could I do?
The problem is you have to initialize each inner Dictionary<string, string> when assigning a new key to your outer dictionary. Typically this means checking if this key exists, and if not, creating the object:
foreach (var item in books)
{
if(!test.ContainsKey(item.Book_Type_ID))
{
test[item.Book_Type_ID] = new Dictionary<string, string>();
}
//now we are sure it exists, add it
test[item.Book_Type_ID][item.Author_ID] = item.Book_Name;
}
The dictionary is 2-dimensional. When you initialize it
Dictionary<string, Dictionary<string, string>> test = new Dictionary<string, Dictionary<string, string>>();
The first dimension is initialized, but not the second - i.e. test is an empty dictionary. So when you try to add a book title to a second-dimension dictionary, there isn't a dictionary for it to be added to yet. You need to check this condition first, and create an entry if it doesn't already exist:
var books = from v in db.Books select v;
Dictionary<string, Dictionary<string, string>> test = new Dictionary<string, Dictionary<string, string>>();
foreach (var item in books)
{
if (!test.ContainsKey(item.Book_Type_ID))
test[item.Book_Type_ID] = new Dictionary<string, string>();
test[item.Book_Type_ID][item.Author_ID] = item.Book_Name;
}
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();
I am getting this error because I have a duplicate key in the SortedList.
Item has already been added. Key in dictionary: 'V22.1' Key being added: 'V22.1'
BUT the value of these duplicate keys are different. So I am thinking of adding another object before the preceding the duplicate key in order to find its value. I was thinking of putting SortedList within a SortedList. An illustration for my intention for example:
(key)"ICD9" : (key)"V22.1" : (value)"Supervision of other normal pregnancy"
(key)"ICD10" : (key)"V22.1" : (value)"Motorcycle passenger injured in collision with two- or three-wheeled motor vehicle in nontraffic accident"
I hope that makes sense. I was thinking of doing something like this:
SortedList<string, SortedList<string, string>> slCodes;
slCodes = new SortedList<string, SortedList<string, string>>();
But the part I am stuck now is how do I add into the SortedList within the SortedList? I am stuck here:
strDesc = tbDesc.Text.Trim();
tblCodes = new DataTable();
GetCodesByDescription(strDesc, ref tblCodes); //<--This queries from database
DataView dvCodes = new DataView(tblCodes);
dvCodes.RowFilter = "CodeType='ICD10' OR CodeType='ICD9'";
foreach(DataRowView drv in dvCodes)
{
slCodes.Add(drv["Code"].ToString().Trim(), //<--Throws error here.
drv["Description"].ToString().Trim());
}
This is currently where I am stuck at on adding into the SortedList within a SortedList. I'm not even sure if this approach to having a key-value pair within a key is correct. Please help.
You need to first check the code type to determine which sub list to add to and if you need to create a new sub list.
foreach(DataRowView drv in dvCodes)
{
var codeType = drv["CodeType"].ToString().Trim();
var code = drv["Code"].ToString().Trim();
var description = drv["Description"].ToString().Trim();
if(slCodes.ContainsKey(codeType))
{
slCodes[codeType].Add(code, description);
}
else
{
var subList = new SortedList<string, string>();
subList.Add(code, description);
slCodes.Add(codeType, subList);
}
}
Alternatively since you only pull ICD9 and ICD10 codes you could prepopulate the two sub lists
var slCodes = new SortedList<string, SortedList<string, string>>();
slCodes.Add("ICD9", new SortedList<string, string>());
slCodes.Add("ICD10", new SortedList<string, string>());
dvCodes.RowFilter = "CodeType='ICD10' OR CodeType='ICD9'";
foreach(DataRowView drv in dvCodes)
{
var codeType = drv["CodeType"].ToString().Trim();
var code = drv["Code"].ToString().Trim();
var description = drv["Description"].ToString().Trim();
slCodes[codeType].Add(code, description);
}
slCodes is a SortedList object containing strings for keys and SortedList <string, string> for values, but you are not adding these types to it; rather 2 string objects.
You need to add a string and a SortedList <string, string>, instead of 2 string objects.
If you want to add something to an existing sorted list in slCodes, then you must first look up said list before adding 2 strings to it.
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;
}
}
i have 3 generic dictionaries
static void Main(string[] args)
{
Dictionary<string, string> input = new Dictionary<string, string>();
input.Add("KEY1", "Key1");
Dictionary<string, string> compare = new Dictionary<string, string>();
compare.Add("KEY1", "Key1");
compare.Add("KEY2", "Key2");
compare.Add("KEY3", "Key3");
Dictionary<string, string> results = new Dictionary<string, string>();
i'd like to take the list of input and compare each value to the compareTo list and if it doesn't exist add it to the results list?
You can use the LINQ Except() method:
foreach (var pair in compare.Except(input))
{
results[pair.Key] = pair.Value;
}
This will perform a set difference (in effect subtracting input from compare and returning what is left over), which we can then add to the results dictionary.
Now, if results has no previous values, and you just want it to be the results from that current operation, you can just do that directly:
var results = compare.Except(input)
.ToDictionary(pair => pair.Key, pair => pair.Value);
This is assuming you want the difference in keys and values. If you had a different value (same key), it would show in the difference.
That is, for your example above results will have:
[KEY2, Key2]
[KEY3, Key3]
But if your example data was:
Dictionary<string, string> input = new Dictionary<string, string>();
input.Add("KEY1", "Key1");
Dictionary<string, string> compare = new Dictionary<string, string>();
compare.Add("KEY1", "X");
compare.Add("KEY2", "Key2");
compare.Add("KEY3", "Key3");
The results would be:
[KEY1, X]
[KEY2, Key2]
[KEY3, Key3]
Due to the fact KEY1's value was different.
If you do want only where keys or values are not contained in the other, you can do the Except on the Keys or Values collections of the dictionary instead.
dict[key] gives you the value whose key is key.
dict.ContainsKey(key) and dict.ContainsValue(value) are methods you can use to check whether a key or a value are in the dictionary. ContainsKey is more time-efficient.