-
May 17th, 2022, 01:33 PM
#1
Thread Starter
New Member
Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 props
Hello all. So I have a List(Of ExpandoObjects) and I need a fast way to determine if an object exists in the list by evaluating 2 properties. I created a function that loops through list and finds the object however, I have a lot of objects in the list and it takes a while because it has to traverse the loop every time I check. I was wondering if there is a faster way. The end result is to be update the datetime of an ExpandoObject property is List1 if the same ExpandoObject exists in List2 based on two prop values. Any feedback is greatly appreciated and thanks for taking the time to read this post.
Here's is my function
Code:
Public Function ObjExistsInListofExpando(ByVal value1 As String, ByVal value2 As String, ByRef List As List(Of ExpandoObject)) As Boolean
Dim returnvalue As Boolean = False
For Each obj As Object In List
If value1 = obj.value1 And value2 = obj.value2 Then
returnvalue = True
Else
returnvalue = False
End If
Next
Return returnvalue
End Function
-
May 17th, 2022, 06:11 PM
#2
Re: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 pro
You could use Linq, but I’m guessing you don’t just want to find an element? It’d make more sense to find an index…
To test for exists…
Code:
Public Function ObjExistsInListofExpando(ByVal value1 As String, ByVal value2 As String, ByVal List As List(Of ExpandoObject)) As Boolean
Return List.Any(function(o) value1 = o.value1 And value2 = o.value2)
End Function
To return an index…
Code:
Public Function ObjIndexInListofExpando(ByVal value1 As String, ByVal value2 As String, ByVal List As List(Of ExpandoObject)) As Integer
Return List.FindIndex(function(o) value1 = o.value1 And value2 = o.value2)
End Function
If the function returns greater than -1 it found the element
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
May 17th, 2022, 10:37 PM
#3
Re: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 pro
OT, do not declare that third parameter ByRef. This is not VB6. The only reason to declare a reference type (i.e. a class) parameter ByRef is if you want to assign a new object to the parameter inside the method and have that reflected in the original variable outside the method.
-
May 17th, 2022, 10:40 PM
#4
Re: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 pro
The code you had originally could have worked except for a major flaw in the logic. Think about it. You are initialising returnvalue to False so what reason have you got to later set it to False? Think about what your code actually does. What if it finds a match on the first item? It will set returnvalue to True. What then? It keeps looking for no reason and, if the next item does match, it sets returnvalue back to False. Does that make any sense? This is why you need to work out the logic first, then write code to explicitly implement that logic. If you had done that, there's no way you'd have come up with code like that. If you were doing this manually then you'd stop looking as soon as you found a match, if the only thing you care about is whether any matches exist. That's the logic that you should have been implementing in code.
-
May 21st, 2022, 08:57 AM
#5
Re: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 pro
Originally Posted by Pdevine74
Hello all. So I have a List(Of ExpandoObjects) and I need a fast way to determine if an object exists in the list by evaluating 2 properties. I created a function that loops through list and finds the object however, I have a lot of objects in the list and it takes a while because it has to traverse the loop every time I check. I was wondering if there is a faster way.
This is precisely why data structures like hash tables were invented:-
Code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim find_x As Long = 908
Dim find_y As Integer = 7812
Dim found_p As Point
Dim points = CreateData()
Dim sw As New Stopwatch
sw.Restart()
'Find the item using a linearly search
For Each p In points
If p.Value.X = find_x AndAlso p.Value.Y = find_y Then
Debug.WriteLine($"Found point : {p.Value.ToString}")
Exit For
End If
Next
sw.Stop()
Debug.WriteLine($"Linear search took {sw.ElapsedMilliseconds.ToString} ms.")
Debug.WriteLine("")
sw.Restart()
'Find the item using the key in the Dictionary
If points.TryGetValue(CreateKey(find_x, find_y), found_p) Then
Debug.WriteLine($"Found point : {found_p.ToString}")
End If
sw.Stop()
Debug.WriteLine($"Hash lookup took {sw.ElapsedMilliseconds.ToString} ms")
End Sub
Private Function CreateData() As Dictionary(Of String, Point)
Dim d As New Dictionary(Of String, Point)
For x = 0 To 1000
For y = 0 To 10000
d.Add(CreateKey(x, y), New Point(x, y))
Next
Next
Return d
End Function
Private Function CreateKey(ByVal x As Integer, ByVal y As Integer) As String
'Creates key from values. Eg X = 12 and Y=34
'will produce a String key of "12_34"
Return $"{x.ToString}_{y.ToString}"
End Function
End Class
The above code measures the performance difference between a linear scan like you did and a keyed look-up. This is the output:-
Code:
Found point : {X=908,Y=7812}
Linear search took 233 ms.
Found point : {X=908,Y=7812}
Hash lookup took 1 ms
As you can see it was able to find a specific Point structure in collection of 10 million Points a whopping 233 times faster in a Dictionary than it did using a linear scan.
The key insight here is to turn all combination of properties you might perform a search on into a single key and use that as the key value for it's entry in a Dictionary.
The above code might look confusing but don't let it fool you. Dictionaries are easy to use. Here is some simpler code demonstrating what you need to do:-
Code:
'Create a Dictionary of points
Dim data = {New Point(34, 12),
New Point(100, 34),
New Point(98, 78)}.ToDictionary(Function(p) $"{p.X.ToString}_{p.Y.ToString}")
'We want to find this X and Y value in the collection
'of points
Dim find_x As Integer = 100
Dim finx_y As Integer = 34
'If the search is successful this variable
'will contain what it found
Dim found_point As Point
'Perform the lookup and store the result in the variable "found_point" if
'the search was successful in finding what we are looking for
If data.TryGetValue(find_x.ToString & "_" & finx_y.ToString, found_point) Then
'This code will execute ONLY if the item was found.
Debug.WriteLine("Success!")
Else
Debug.WriteLine("Item not found.")
End If
The above shows how use a Dictionary to find an object with a specific combination of values in it's properties by combining both values into a key which is stored with the object itself in a Dictionary.
Last edited by Niya; May 21st, 2022 at 10:57 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|