cklester Well-Known Member Licensed User Jan 15, 2021 #1 I guess I can move this to the tutorials section, since this seems to work just fine: Code: Copy 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: Jan 15, 2021
I guess I can move this to the tutorials section, since this seems to work just fine: Code: Copy 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?
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #2 cklester said: I guess I can move this to the tutorials section, Click to expand... to "Code Snippets" Upvote 0
cklester said: I guess I can move this to the tutorials section, Click to expand... to "Code Snippets"
Daestrum Expert Licensed User Longtime User Jan 15, 2021 #3 One minor note - it only works if the maps are in the same order. Upvote 0
cklester Well-Known Member Licensed User Jan 15, 2021 #4 Daestrum said: One minor note - it only works if the maps are in the same order. Click to expand... Ah, so there's the flaw in this design. Still have to check each key and each value? Upvote 0
Daestrum said: One minor note - it only works if the maps are in the same order. Click to expand... Ah, so there's the flaw in this design. Still have to check each key and each value?
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #5 Daestrum said: One minor note - it only works if the maps are in the same order. Click to expand... What do you mean? Upvote 0
Daestrum said: One minor note - it only works if the maps are in the same order. Click to expand... What do you mean?
Daestrum Expert Licensed User Longtime User Jan 15, 2021 #6 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
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}
cklester Well-Known Member Licensed User Jan 15, 2021 #7 I guess I could use a sorted map, but I was definitely hoping not to have to explore embedded maps. Upvote 0
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #8 Daestrum said: 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} Click to expand... B4X code, please Upvote 0
Daestrum said: 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} Click to expand... B4X code, please
Daestrum Expert Licensed User Longtime User Jan 15, 2021 #9 try this Code: Copy 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
try this Code: Copy 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
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #10 Daestrum said: try this Code: Copy 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 Click to expand... That is wrong. You don't know what mp1 & mp2 Get(key) will return. It would work only with "simple" data types (string, int, ...) Upvote 0
Daestrum said: try this Code: Copy 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 Click to expand... That is wrong. You don't know what mp1 & mp2 Get(key) will return. It would work only with "simple" data types (string, int, ...)
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #11 Daestrum said: 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} Click to expand... Yes, this do not work: B4X: Copy Dim m1, m2 As Map m1.Initialize m1.Put("a", "ciao") m1.Put("B", 123) m2.Initialize m2.Put("B", 123) m2.Put("a", "ciao") Log(MapsAreSame(m1, m2)) Log(MapsAreSame(m2, m1)) Log: False False Upvote 0
Daestrum said: 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} Click to expand... Yes, this do not work: B4X: Copy Dim m1, m2 As Map m1.Initialize m1.Put("a", "ciao") m1.Put("B", 123) m2.Initialize m2.Put("B", 123) m2.Put("a", "ciao") Log(MapsAreSame(m1, m2)) Log(MapsAreSame(m2, m1)) Log: False False
alwaysbusy Expert Licensed User Longtime User Jan 15, 2021 #12 With this slight modification you could also handle embedded maps (maybe other data types need a similar check): Code: Copy 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
With this slight modification you could also handle embedded maps (maybe other data types need a similar check): Code: Copy 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
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #13 This part is not correct. alwaysbusy said: If mp1.Get(key) <> mp2.Get(key) Then Return False Click to expand... 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. Also, AreEqual should be recursive, since mp1.Get(key) might be a "map of maps". Upvote 0
This part is not correct. alwaysbusy said: If mp1.Get(key) <> mp2.Get(key) Then Return False Click to expand... 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. Also, AreEqual should be recursive, since mp1.Get(key) might be a "map of maps".
alwaysbusy Expert Licensed User Longtime User Jan 15, 2021 #14 LucaMs said: 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. Click to expand... Hence,... alwaysbusy said: maybe other data types need a similar check Click to expand... LucaMs said: Also, AreEqual should be recursive, since mp1.Get(key) might be a "map of maps". Click to expand... This handles the recursive alwaysbusy said: If mp1.Get(key) Is Map Then If areEqual(mp1.Get(key),mp2.Get(key)) = False Then Return False Else ... Click to expand... Alwaysbusy Upvote 0
LucaMs said: 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. Click to expand... Hence,... alwaysbusy said: maybe other data types need a similar check Click to expand... LucaMs said: Also, AreEqual should be recursive, since mp1.Get(key) might be a "map of maps". Click to expand... This handles the recursive alwaysbusy said: If mp1.Get(key) Is Map Then If areEqual(mp1.Get(key),mp2.Get(key)) = False Then Return False Else ... Click to expand... Alwaysbusy
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #16 alwaysbusy said: If mp1.Get(key) <> mp2.Get(key) Then Click to expand... Since this line would not be effective if the two elements were objects, whose contents you want to compare and not their pointers, you should serialize them first. Upvote 0
alwaysbusy said: If mp1.Get(key) <> mp2.Get(key) Then Click to expand... Since this line would not be effective if the two elements were objects, whose contents you want to compare and not their pointers, you should serialize them first.
Erel B4X founder Staff member Licensed User Longtime User Jan 15, 2021 #17 If you want to support maps that hold other collections or custom types then using serialization is probably the best option. You will need to replace the second map with a new one where the keys are added in the order of the first map. Upvote 0
If you want to support maps that hold other collections or custom types then using serialization is probably the best option. You will need to replace the second map with a new one where the keys are added in the order of the first map.
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #18 Erel said: If you want to support maps that hold other collections or custom types then using serialization is probably the best option. You will need to replace the second map with a new one where the keys are added in the order of the first map. Click to expand... This work just needs... a lot of work (and creating an entire class-library, probably) Upvote 0
Erel said: If you want to support maps that hold other collections or custom types then using serialization is probably the best option. You will need to replace the second map with a new one where the keys are added in the order of the first map. Click to expand... This work just needs... a lot of work (and creating an entire class-library, probably)
LucaMs Expert Licensed User Longtime User Jan 15, 2021 #19 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: Jan 15, 2021 Upvote 0
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 ...)
cklester Well-Known Member Licensed User Jan 15, 2021 #20 OK, so how about this (works for me but not extensively tested): Code: Copy 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: Jan 15, 2021 Upvote 0
OK, so how about this (works for me but not extensively tested): Code: Copy 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? ?