Removing item from Dictionary in VB.net - vb.net

I have something like this:
Public Shared Property PinnedChannelConnectionIds() As Dictionary(Of Integer, List(Of String))
Get
If _pinnedChannelConnectionIds Is Nothing Then
Return New Dictionary(Of Integer, List(Of String))
Else
Return _pinnedChannelConnectionIds
End If
End Get
Set(value As Dictionary(Of Integer, List(Of String)))
_pinnedChannelConnectionIds = value
End Set
End Property
And then, have some data in dictionary as :
1, {"c1","c2", "c3"}
2, {"c2","c4", "c6"}
3, {"c3","c5", "c1"}
4, {"c4","c3", "c6"}
So to remove a specific item. Let say "c2" from the above dictionary.
I am doing like this:
For Each channelKeyValuePair As KeyValuePair(Of Integer, List(Of String)) In Channel.PinnedChannelConnectionIds
For Each item As String In channelKeyValuePair.Value.ToList()
If (item.Equals("c2")) Then
Channel.PinnedChannelConnectionIds(channelKeyValuePair.Key).Remove(item)
End If
Next
Next
But it throws error : Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
Can anyone please help me out.
Thanks in advance!!

I'd suggest something like
For Each channelKeyValuePair As KeyValuePair(Of Integer, List(Of String)) In Channel.PinnedChannelConnectionIds
channelKeyValuePair.Value.RemoveAll(Function(x) x = "C2")
Next
might work. There's no need to iterate over the list elements to find and remove them and it can cause difficulties of the sort you are experiencing.

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)

VB.Net Order values in a List of Dictionaries

I'm working with a List of Dictionaries. I want to order each Dictionary inside the list by its values. I'm trying these two options:
1)
Dim myList As List(Of Dictionary(Of Integer, Single))
myList.ForEach(Function(x) x.OrderBy(Function(a) a.Value).ToDictionary(Function(y) y.Key, Function(y) y.Value))
2)
Dim myList As List(Of Dictionary(Of Integer, Single))
For Each element In myList
element = element.OrderBy(Function(a) a.Value).ToDictionary(Function(y) y.Key, Function(y) y.Value)
Next
However, none of these works. Can somebody help me?

How to sort the keys of a dictionary in reverse order using VB.NET?

I have a dictionary:
Dim dicItems As Dictionary(of Integer, String)
The items in the dictionary are:
1,cat
2,dog
3,bird
I would like the order to be:
3,bird
2,dog
1,cat
You can't sort a dictionary, what you need is a sorted list instead.
Dim dicItems As New SortedList(Of Integer, String)
This will sort the items by the key value. If you want to get the items out in descending order like your example you could always do a loop starting from the end of the list, and moving to the beginning.
The below link has more information on SortedList's.
http://msdn.microsoft.com/en-us/library/ms132319%28v=vs.110%29.aspx
You can use LINQ to solve this easily:
Dim dicItems As New Dictionary(Of Integer, String)
With dicItems
.Add(1, "cat")
.Add(2, "dog")
.Add(3, "bird")
End With
dim query = from item in dicItems
order by item.Key descending
select item
If you want, you can also use the Lambda syntax:
Dim query = dicItems.OrderByDescending(Function(item) item.Key)
A dictionary has no implicit order that you can rely on ("The order in which the items are returned is undefined").
As add-on for Shadows answer who suggest to use a SortedList you can get descending order by using the constructor that takes an IComparer(Of Int32):
Dim list = New SortedList(Of Integer, String)(New DescendingComparer())
list.Add(3, "bird")
list.Add(1, "cat")
list.Add(2, "dog")
Public Class DescendingComparer
Implements IComparer(Of Int32)
Public Function Compare(x As Integer, y As Integer) As Integer Implements System.Collections.Generic.IComparer(Of Integer).Compare
Return y.CompareTo(x)
End Function
End Class
Not sure why you would want to, since an order of items in the dictionary usually does not matter, but you can do it like this:
Dim dicItems As New Dictionary(Of Integer, String)
With dicItems
.Add("1", "cat")
.Add("2", "dog")
.Add("3", "bird")
End With
Dim dicItemsReversed As New List(Of KeyValuePair(Of Integer, String))
dicItemsReversed.AddRange(dicItems.Reverse())
Notice that I output to a different collection, i.e. Generic.List in this case. If you want to replace your original contents, you can then do this:
dicItems.Clear()
For Each kv In dicItemsReversed
dicItems.Add(kv.Key, kv.Value)
Next
As a variation on the topic, you can replace dicItems.Reverse() with other LINQ alternatives, such as OrderBy, so you can, for example, sort by Key, Value or a combination thereof. For example this dicItems.OrderBy(Function(x) x.Value) gives the output of:
3,bird
1,cat
2,dog
(sorted alphabetically by value, ascending order)

VB dictionary contains value return key

I have a problem...
I am trying to put into a list of String dictionary keys values if condition of containsvalue is true:
But, this is not correct :(
here is a code:
Private listID As New List(Of String) ' declaration of list
Private dictionaryID As New Dictionary(Of String, Integer) ' declaration of dictionary
'put a keys and values to dictionary
dictionaryID.Add("first", 1)
dictionaryID.Add("second", 2)
dictionaryID.Add("first1", 1)
If dictionaryID.ContainsValue(1) Then ' if value of dictinary is 1
Dim pair As KeyValuePair(Of String, Integer)
listID.Clear()
For Each pair In dictionaryID
listID.Add(pair.Key)
Next
End If
And now, list must have two elements... -> "first" and "first1"
Can you help me?
Thank you very much!
You are looping through the whole dictionary and add all the elements to the list. You should put an if statement in the For Each or use a LINQ query like this:
If listID IsNot Nothing Then
listID.Clear()
End If
listID = (From kp As KeyValuePair(Of String, Integer) In dictionaryID
Where kp.Value = 1
Select kp.Key).ToList()
Using an if statement:
listID.Clear()
For Each pair As KeyValuePair(Of String, Integer) In dictionaryID
If pair.Value = 1 Then
listID.Add(pair.Key)
End If
Next
My VB.Net is a little rusty, but it looks like you were adding all of them, no matter if their value was 1 or not.
Private listID As New List(Of String) ' declaration of list
Private dictionaryID As New Dictionary(Of String, Integer) ' declaration of dictionary
'put a keys and values to dictionary
dictionaryID.Add("first", 1)
dictionaryID.Add("second", 2)
dictionaryID.Add("first1", 1)
If dictionaryID.ContainsValue(1) Then ' if value of dictinary is 1
Dim pair As KeyValuePair(Of String, Integer)
listID.Clear()
For Each pair In dictionaryID
If pair.Value = 1 Then
listID.Add(pair.Key)
End If
Next
End If

Compare two lists 2D and determine differences VB.NET

I declare my 2D lists:
Dim _invoiceitems As New List(Of List(Of String))
Dim _dbitems As New List(Of List(Of String))
Each List is filled like this:
Example Code To fill:
_invoiceitems.Add(New List(Of String))
_invoiceitems(0).Add("Code #")
_invoiceitems(0).Add("Quantity")
Well, now i need a third list called (_changesitems) Note that this result with the differences:
be the result of subtraction of quantities if this is found (dbitems - invoiceitems).
How i can get this result?
The following code will generate the results you are looking for:
Private Function getChangesItems(ByVal invoiceItems As Dictionary(Of String, Integer), ByVal dbItems As Dictionary(Of String, Integer)) As Dictionary(Of String, Integer)
Dim changesItems As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()
Dim allCodes As List(Of String) = New List(Of String)()
allCodes.AddRange(invoiceItems.Keys)
allCodes.AddRange(dbItems.Keys)
For Each code As String In allCodes
If Not changesItems.ContainsKey(code) Then
Dim dbQuantity As Integer = 0
Dim invoiceQuantity As Integer = 0
If dbItems.ContainsKey(code) Then
dbQuantity = dbItems(code)
End If
If invoiceItems.ContainsKey(code) Then
invoiceQuantity = invoiceItems(code)
End If
Dim changeQuantity As Integer = dbQuantity - invoiceQuantity
If changeQuantity <> 0 Then
changesItems.Add(code, changeQuantity)
End If
End If
Next
Return changesItems
End Function
I used dictionaries instead of lists as was recommended by others. As long as your data only contains a code and a value, the dictionary is a better fit. If you have more columns, I would suggest creating a class that contains properties for each column and then make a list of that class type, rather than a simple 2D list of strings. Doing so would be more type-safe and easier to read.