B4J Question Compare Two Maps

cklester

Well-Known Member
Licensed User
I guess I can move this to the tutorials section, since this seems to work just fine:

B4X:
Sub BuffersEqual (b1() As Byte, b2() As Byte) As Boolean
    If b1.Length <> b2.Length Then Return False
    For i = 0 To b1.Length - 1
        If b1(i) <> b2(i) Then Return False
    Next
    Return True
End Sub

'name this whatever you want!
Public Sub MapsAreSame(aMap as Map, bMap as Map) As Boolean
    Dim ser As B4XSerializator
    Dim am() As Byte = ser.ConvertObjectToBytes(aMap)
    Dim bm() As Byte = ser.ConvertObjectToBytes(bMap)
    Return BuffersEqual(am,bm)
End Sub

Is this an acceptable way to do it?
 
Last edited:

Daestrum

Expert
Licensed User
Longtime User
If you have 2 maps

m1 (MyMap) {a=Letter a, b=Letter b, c=Letter c}

m2 (MyMap) {c=Letter c, b=Letter b, a=Letter a}
 
Upvote 0

cklester

Well-Known Member
Licensed User
I guess I could use a sorted map, but I was definitely hoping not to have to explore embedded maps.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
try this
B4X:
Sub areEqual(mp1 As Map ,mp2 As Map) As Boolean
    If mp1.Size<>mp2.Size Then Return False
    For Each key As Object In mp1.Keys
        If mp1.Get(key) <> mp2.Get(key) Then Return False
    Next
    Return True
End Sub
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
With this slight modification you could also handle embedded maps (maybe other data types need a similar check):

B4X:
Sub areEqual(mp1 As Map ,mp2 As Map) As Boolean
    If mp1.Size<>mp2.Size Then Return False
    For Each key As Object In mp1.Keys
        If mp1.Get(key) Is Map Then
            If areEqual(mp1.Get(key),mp2.Get(key)) = False Then Return False
        Else
            If mp1.Get(key) <> mp2.Get(key) Then Return False
        End If    
    Next
    Return True
End Sub

Alwaysbusy
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
If mp1.Get(key) and mp1.Get(key) returned a String, Int, Float, Double, ... ("simple" type) it would be ok, but if they returned and object not.
Hence,...
maybe other data types need a similar check

Also, AreEqual should be recursive, since mp1.Get(key) might be a "map of maps".
This handles the recursive
If mp1.Get(key) Is Map Then
If areEqual(mp1.Get(key),mp2.Get(key)) = False Then Return False
Else
...

Alwaysbusy
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Better (quickest) solution: add a Map Id to your Maps 😄


EDIT:
I probably wrote yet another nonsense:
comparing the two Ids would be the same as comparing the Map objects themselves (their pointer: If m1 = m2 ...)
 
Last edited:
Upvote 0

cklester

Well-Known Member
Licensed User
OK, so how about this (works for me but not extensively tested):

B4X:
Private Sub isSame(a As Object, b As Object) As Boolean
    Dim ser As B4XSerializator
    Dim ab() As Byte = ser.ConvertObjectToBytes(a)
    Dim bb() As Byte = ser.ConvertObjectToBytes(b)
    For i = 0 To ab.Length - 1
        If ab(i) <> bb(i) Then Return False
    Next
    Return True
End Sub

Sub MapsAreEqual(mp1 As Map ,mp2 As Map) As Boolean
    If mp1.Size <> mp2.Size Then Return False
    For Each Key As Object In mp1.Keys
'        Log(Key)
        If mp1.Get(Key) Is Map Then
            If mp2.Get(Key) Is Map Then
                If MapsAreEqual(mp1.Get(Key),mp2.Get(Key)) = False Then
'                    Log("Maps for " & Key & " are not equal.")
                    Return False
                End If
            Else
                Return False
            End If
        Else
            If Not(isSame(mp1.Get(Key),mp2.Get(Key))) Then
'                Log("Unequal is " & Key)
'                Log(mp1.Get(Key))
'                Log(mp2.Get(Key))
                Return False
            End If
        End If
    Next
    Return True
End Sub

Can anybody find a breaking case? 😁
 
Last edited:
Upvote 0
Top