Results 1 to 5 of 5

Thread: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 props

  1. #1

    Thread Starter
    New Member
    Join Date
    May 2022
    Posts
    3

    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

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    24,812

    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

  3. #3
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    108,498

    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.

  4. #4
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    108,498

    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.

  5. #5
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    7,596

    Re: Fast way to determine if an obj exists in a List(Of ExpandoObject) based on 2 pro

    Quote Originally Posted by Pdevine74 View Post
    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width