nested dictionaries - vb.net

I've got a nested dict like:
Public collectionMain As New Dictionary(Of String, Dictionary(Of String, String))
When inserting a new item:
collectionMain.Add(node.SelectSingleNode("key").InnerText.Trim, collectionSub)
collectionSub.Clear()
On the add my collectionSub is filled with key & values.
But when calling clear, the collectionMain.value is empty.
How can i keep the collectionMain dictionary value?
The collectionSub needs to be cleared, it's in a loop for filling.
thank you

You need to create a New Dictionary(Of String, String) for each value.

Whenever you add a new dictionary item, you will have to declare a new sub-dictionary for that key:
collectionMain.Add(node.SelectSingleNode("key").InnerText.Trim, _
New Dictionary(Of String, String))
The collectionSub variable really should not exist since every key in collectionMain has it's own dictionary.

Do not clear collectionSub. Don't forget that you are adding reference of Dictionary(Of String, String) - collectionSub. If you want to clear that object then you must have to create a "clone" (deep copy) of collectionSub. Take a look at SO thread - What is the best way to clone/deep copy a .NET generic Dictionary?

Related

How can i change the values in a dictionary that are inside another dictionary?

I've come here after hours of looking on the internet. Nothing comes close to what I am trying to achieve.
I have this:-
Private Portfolio_Client_List As New Dictionary(Of String, Dictionary(Of String, Double))
which I then add keys to like the following:-
Portfolio_Client_List.Add(str.Substring(6, 5).Trim, New Dictionary(Of String, Double))
then I add keys to the other dictionary like the below:-
For Each pair As KeyValuePair(Of String, Dictionary(Of String, Double)) In Portfolio_Client_List
pair.Value.Add("Office Collections", 0.00)
pair.Value.Add("Home Collections", 0.00)
Next
Now I want to update the values in the Office Collections and Home Collections keys values.
How can I do so? I thought it would be as simple as:-
For Each pair As KeyValuePair(Of String, Double) In Portfolio_Client_List("key")
pair.Value += Head_Office_Payments
Next
However it just gives me the readonly error. Is there any way to do this, or am I wasting my time?
No, KeyValuePairs are immutable structs, so you can't modify them, Value is readonly.
But this works (you want to add Head_Office_Payments to the old value):
Dim dict As Dictionary(Of String, Double) = Portfolio_Client_List("key")
For Each key As String In dict.Keys.ToList()
dict(key) += Head_Office_Payments
Next
Note that you need the dict.Keys.ToList(creates a new list) because you can't modify the collection while enumerating, setting the Value of a dictionary increases it's version number which invalidates the iterator. That's why i prefer this one-liner LINQ solution:
dict = dict.ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value + Head_Office_Payments)

Which overload of todictionary that I use if I do this?

Dim dict1 = fileToDict(PriceList)
Dim dict2 = dict1.ToDictionary(Function(y) Val(y))
Basically I am turning dict(of string,string) to dict(of string, double).
My question is I do not see any overload of toDictionary that takes a single function of stuff.
Note: The correct format is actually
Dim dict2 = dict1.ToDictionary(Function(x) x.Key, Function(y) Val(y.Value))
All of the overloaded operator takes 1 function that takes a keyvaluepair as argument.
Somehow the one that works use 2 function. That's where I am confused.
You need to specify a selector for both the keys and the values. There's no overload that is going to simply take the keys from the original Dictionary. Remember that ToDictionary is actually called on an IEnumerable(Of T) so it has no idea that the source is a Dictionary. It only knows that it is an IEnumerable(Of KeyValuePair(Of String, String)). You have to tell it how to get the keys for the new Dictionary from the items in the IEnumerable(Of T) source.
E.g.
Dim dict2 = dict1.ToDictionary(Function(kvp) kvp.Key, Function(kvp) CDbl(kvp.Value))

Vb.net access an item in a list inside a dictionary

I created a Dictionary in VB.net to contained a list
Dim dic As New Dictionary(Of String, List(Of Double))
Then on a loop I add a Key and Items to the list.
dic.Add("Key1", New List(Of Double))
do some stuff and add the items to the list of the key
Dic("Key1").Add(1.1078)
Dic("Key1").Add(12.232)
Dic("Key1").Add(33.365)
etc
How Do I access the value of the list using a Key
Console.writeline(Dic.Item("Key1")(1))
I was trying to print index 1 of the list associated with Key1
but I get a crash
Thanks
Kiko
You have found the answer meanwhile. I would just like to add that a safer method would be to use TryGetValue:
Dim list As List(Of Double)
If dic.TryGetValue("Key1", list) Then
Console.WriteLine(list(0))
Else
Console.WriteLine("Key1 not found!")
End If
It is so simple.
dic("key1").item(1)

DateTime as Object in dictionary

I have read here that a dictionary (of string, object) can hold multiple variable types. However, in the function below, endTime does not appear to get assigned. The line Console.Write(lobjWaveOutList(0)("endTime")) in the code below gives me the error 'the given key was not present in the dictionary'.
Private lobjWaveOutList As New List(Of Dictionary(Of String, Object))()
Public Sub addIndex(waveOut As Object, endTime As DateTime)
Console.WriteLine("endTime:")
Console.WriteLine(endTime)
lobjWaveOutList.Add(New Dictionary(Of String, Object)() From {{"waveOut", waveOut}})
lobjWaveOutList.Add(New Dictionary(Of String, Object)() From {{"endTime", endTime}})
Console.Write(lobjWaveOutList(0)("endTime"))
End Sub
I called the addIndex function with the following parameters:
waveouts.addIndex(New WaveOut(), DateTime.Now.AddSeconds(10))
lobjWaveOutList(0)("endTime") will not work because it is accessing the first dictionary in the list, which only contains a "waveOut" item. The "endTime" item is in the second dictionary in the list. To get that one, you'd need to do this:
Console.Write(lobjWaveOutList(1)("endTime"))
As Neolisk pointed out, it would seem more appropriate, based on your example, to simply have a single dictionary, containing multiple items, rather than a list of dictionaries, each only containing a single item.
As you have a list of Dictonary "endtime" is here: lobjWaveOutList(1)("endTime")

List of Dictionary Arrays

Hit a wall, and can't find much in docs.
I have two dictionaries, and I'd like to put them in a list.
Dim listOfDictionaries As List(Of Dictionary(Of String, String))
is not working.
Am I correct in assuming that once I get this dimmed, I can .add the conventional way?
Details (EDIT)
When trying to listOfDictionaries.Add(dictionaryIWantToAdd), I get "value of type '1-dimensional array system.collection.generic.dictionary(of string, string)' cannot be converted to 'system.collection.generic.dictionary(of string, string)'
Solution
Helps to put the () on the end an array. :P
The conventional way is:
Dim both = New List(Of Dictionary(Of String, String))()
both.Add(Dictionary1)
both.Add(Dictionary2)
The error says it all. You are trying to add an array of dictionaries to the list, but the add method only takes a single dictionary, not an array of them. Either fix it so you are only passing in a single dictionary:
Dim myDictionary As Dictionary(Of String, String)
' ...
listOfDictionaries.Add(myDictionary)
Or use the AddRange method to add all the dictionaries in the array at once:
Dim myArrayOfDictionaries() As Dictionary(Of String, String)
' ...
listOfDictionaries.AddRange(myArrayOfDictionaries)
I tend to favour single-line solutions when it's something straightforward like this, making use of the From keyword.
Dim listOfDictionaries = New List(Of Dictionary(Of String, String)) From { dictionary1, dictionary2 }