List of Dictionary Arrays - vb.net

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 }

Related

Convert Dictionary(Of String, Object) to Dictionary(Of String, String)

When I try to pass a Dictionary(Of String, Object) to a function parameter that wants a Dictionary(Of String, String) I get the following error:
Unable to cast object of type 'System.Collections.Generic.Dictionary'2[System.String,System.Object]' to type 'System.Collections.Generic.Dictionary'2[System.String,System.String]'.
All of the Object values in the dictionary are strings but the dictionary was declared as String/Object. I would have thought that the system would be able to convert this but since it isn't I need to do it myself.
I looked at the .ToDictionary() prototype method but all of the examples show a list being converted to a dictionary.
I found this question which has an accepted answer for what I want but it's written in C# and I can't figure out the conversion to VB.Net.
Edit 1
Offending code. Obviously boiled down or else I would just simply declare dict1 as string/string in my actual code.
Dim dict1 As New Dictionary(Of String, Object) From {{"key1","value1"}}
SomeFunctionThatExpectsParamToBeDictOfStringString(dict1)
Edit 2
I tried:
SomeFunctionThatExpectsParamToBeDictOfStringString(dict1.ToDictionary(Function(k) k.Key, Function(v) v.Value.ToString()))
but got:
System.MissingMemberException: Public member 'ToDictionary' on type 'Dictionary(Of String,Object)' not found.
This could be the VB.NET version of the C# code you have linked
Dim dic1 As Dictionary(Of String, Object) = New Dictionary(Of String, Object)
dic1.Add("A", "B")
Dim dic2 As Dictionary(Of String, String) = dic1.ToDictionary(Function(k) k.Key,
Function(v) v.Value.ToString())

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

What collection method should I use?

I have a text file and it looks like this
defabot:3215
defatank:2985
ludditus:29
compensate:355
moobot:805
maxi292003:63
doctorbarzhal:19
plaanz:4
manguuu:51
atntpc:19
immortalsofthemist:18
I'm loading this list when my application opens, splitting the name from number and populating a listview control with it. I want to maintain the list in memory for my entire project to use and manipulate.
I need the numbers associated with the name so when I search for the name I know how many points they have. What is the most efficient/easiest way to accomplish this?
Thank you.
Use Dictionary(Of String, Integer). Here is an example:
Dim dict As New Dictionary(Of String, Integer)
For Each s As String In IO.File.ReadAllLines("filename")
Dim a() As String = s.Split(":"c)
Dim userName As String = a(0)
Dim userPoints As Integer = Convert.ToInt32(a(1))
dict.Add(userName, userPoints)
Next
The most efficient way is to use a Dictionary(Of String, Int32):
Dim dict As Dictionary(Of String, Int32) = IO.File.ReadLines(path).
Select(Function(line) line.Split(":"c)).
ToDictionary(Function(split) split(0), Function(split) Int32.Parse(split(1)))
You get the value by it's key:
Dim ludditus As Int32 = dict("ludditus")

nested dictionaries

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?