I have a list of objects within another list. It looks like this:
Dim _elements as List(Of List(Of Element))
_elements(0) is a list of Element1, Element2, etc.
_elements(1) is a list of Element5, Element6, etc.
I need to create a dictionary of the elements so that the index of each list is the Key in the dictionary. The value of the dictionary should hold all elements of the Legend type that can be found in the list. Something like the following:
Dim legendElements As New Dictionary(Of Integer, List(Of Element))
' Initialize the list in the dictionary
For i As Integer = 0 To _elements.Count - 1
legendElements(i) = new List(Of Element)
Next
For i As Integer = 0 To _elements.Count - 1
For each element as Element in _elements(i)
If element.GetType() Is GetType(Legend) Then
legendElements.add(element)
End If
Next
Next
Is there a System.Linq function that can do the equivalent as the example above?
Call Enumerable.SelectMany method to get a flatten list of the target type which you filter by calling the Enumerable.Where method. Call the Enumerable.Select method to create from the result IEnumerable of anonymous objects to hold and pass the Legend objects along with their indices, and finally, call the Enumerable.ToDictionary method to create
Dictionary(Of Integer, Element) from the anonymous objects.
Dim legendElements As Dictionary(Of Integer, Element) = elements.
SelectMany(Function(x) x.Where(Function(y) y.GetType Is GetType(Legend))).
Select(Function(v, k) New With {Key .Key = k, .Value = v}).
ToDictionary(Function(a) a.Key, Function(a) a.Value)
Do the proper cast if you need a Dictionary(Of Integer, Legend).
Dim legendElements As Dictionary(Of Integer, Legend) = elements.
SelectMany(Function(x) x.Where(Function(y) y.GetType Is GetType(Legend))).
Select(Function(v, k) New With {Key .Key = k, .Value = v}).
ToDictionary(Function(a) a.Key, Function(a) DirectCast(a.Value, Legend))
Related
I'd like to repeatedly add lists of strings to a bigger list collection, but it seems that the list.add function is adding the items byref. How can I change the below example code to pass the elements byval so that they're not cleared when I re-use variables:
Dim inner As New List(Of String)
Dim outer As New List(Of List(Of String))
Dim eleCount As Integer = 0
lbltop:
inner.Add("a")
inner.Add("b")
inner.Add("c")
outer.Add(inner)
Debug.Write(outer(0)(0).ToString())
inner.Clear()
Debug.Write(outer(0)(0).ToString())
eleCount += 1
If eleCount < 2 Then
GoTo lbltop
End If
this writes a then there's an out of range exception for the next debug.write statement.
I'd like it to write aa then loop to add another inner element.
List<T> is a reference type. Only way to not effect it when calling Clear() is to add a clone of it to outer instead. You can do so by using .ToList()
outer.Add(inner.ToList())
But I actually think the most clear way is to instead assign inner a new List instead of calling Clear, than you dont have to do above.
inner = new List(Of String)
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?
I'm writing a bit of code that I want to populate a TreeView, which it does quite successfully, but I also want to put a Dictionary in the Tag of each Level 1 child node. Once the Tag has been set to the Dictionary, is there any way I can modify the dictionary, without redeclaring the Tag.
For Each verse In Verses
Dim _verse = verse.ToString.Trim
Dim _node As TreeNode = New TreeNode(_verse.Split(vbNewLine).First & "...")
_node.ToolTipText = _verse
_node.Tag = New Dictionary(Of String, Object)
Node.Nodes.Add(_node)
Next
You can later just cast the tag of the not to Dictionary(Of String, Object) and then manipulate the dictionary as usual.
For example, assuming that currentNode is the node of interest, you can have something like the following.
Dim dictionary as Dictionary(Of String, Object) = _
CType(currentNode.Tag, Dictionary(Of String, Object))
dictionary.Add("NewKey", newObject);
is it possible to find a complete object in list of objects?
dim list1 as list(of class1) = alist
dim x as class1
how to find x in list1 if it exists without comparing a single property like ID ?
The Contains method will return true if the element is in the list.
dim list1 as list(of class1) = alist
dim x as class1
list1.Contains(x)
If I have a list...
dim l as List(of MyClass) = new List(of MyClass)
and I want to get the type of the objects contained in the list, how do I do that?
The obvious answer, that doesn't seem to be possible from my actual implementation, would be to do something like this...
public function GetType(byval AList as IList(of GenericType)) as System.Type
dim lResult as system.type = nothing
if AList.Count > 0 then lResult = AList(0).GetType
return lResult
end function
But what if the list is empty and I still want to know the type it contains?
There's a good article on this at MSDN, here
Basically you can use GetGenericArguments() to get an array of the types provided as arguments to your generic type. In the case of a List, there's only one argument so you will get what you need using eg
dim l as List(of MyClass) = new List(of MyClass)
dim t as Type = (l.GetGenericArguments())(0)