2

I need to create third array from difference of two arrays, I simply can not get the logic of this

The correct third array v3 would be (from the code below) v3 = (Carol, Ted, Thor, Freya)

Thanks

Sub MatchArrays()
Dim v1, v2, v3
Dim i As Long, j As Long

v1 = Array("Bob", "Carol", "Ted", "Alice", "Thor", "Freya")
v2 = Array("Bob", "Carol")

ReDim v3(LBound(v1) To Abs(UBound(v1) - UBound(v2)))

For i = LBound(v1) To UBound(v1)
   For j = LBound(v2) To UBound(v2)
     If InStr(1, v1(i), v2(j)) Then
       v3(i) = v1(i)
       Exit For
     End If
   Next j
  MsgBox v3(i)
Next i
End Sub
5
  • Is one array always going to be a subset of the other? Commented Nov 9, 2015 at 0:01
  • 1
    And why would that be the result for the example shown? Commented Nov 9, 2015 at 0:16
  • @Tim, Yes one will always be a subset of the other. @shg, v3 is the result I am looking to get Commented Nov 9, 2015 at 0:47
  • I think the question is why Carol is in v3 if Carol is in both v1 and v2? Seems like v3 should be "Ted", "Alice", "Thor", "Freya" since they're only in v1. Commented Nov 9, 2015 at 1:28
  • 1
    @DougGlancy, Your right should be v3 = (Ted, Alice, Thor, Freya) Commented Nov 9, 2015 at 1:33

3 Answers 3

3

This one uses Collections and the fact that adding a duplicated key raises an error. It doesn't matter whether v1 or v2 is the subset:

Sub test()
Dim v1 As Variant, v2 As Variant, v3 As Variant
Dim coll As Collection
Dim i As Long

'Assumes 0-based Variants
v1 = Array("Bob", "Carol", "Ted", "Alice", "Thor", "Freya")
v2 = Array("Bob", "Carol")
ReDim v3(LBound(v1) To Abs(UBound(v2) - UBound(v1)) - 1)

Set coll = New Collection
For i = LBound(v1) To UBound(v1)
    coll.Add v1(i), v1(i)
Next i
For i = LBound(v2) To UBound(v2)
    On Error Resume Next
    coll.Add v2(i), v2(i)
    If Err.Number <> 0 Then
        coll.Remove v2(i)
    End If
    On Error GoTo 0
Next i
For i = LBound(v3) To UBound(v3)
    v3(i) = coll(i + 1) 'Collections are 1-based
    Debug.Print v3(i)
Next i
End Sub
Sign up to request clarification or add additional context in comments.

1 Comment

I chose this as it makes it so I do not have to know which is the subset, thank you
2

Try this:

Sub Test()

Dim v1, v2, v3
Dim i As Long, j As Long
Dim str As String

v1 = Array("Bob", "Carol", "Ted", "Alice", "Thor", "Freya")
v2 = Array("Bob", "Carol")

ReDim v3(LBound(v1) To Abs(UBound(v1) - UBound(v2)))

For i = LBound(v1) To UBound(v1) 'Assuming, that v2 is always the subset of v1

str = v1(i)

If Not IsInArray(str, v2) Then

v3(j) = v1(i)
MsgBox v3(j)
j = j + 1

End If

Next

End Sub

Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function

3 Comments

I had a similar problem the other day, and stumbled upon this article
Worth noting that Filter matches on substrings: Join(Filter(Array("Timothy","Tim"),"Tim"),",") ->> "Timothy,Tim"
This is true! Thanks for pointing this out! One would probably have to use Lensomewhere to check, that the stringToBeFound and the found string have the same length.
1

I believe this is what you want:

Sub MatchArrays()
Dim v1, v2, v3
Dim i As Long, j As Long
Dim here As Boolean
Dim f As Long
v1 = Array("Bob", "Carol", "Ted", "Alice", "Thor", "Freya")
v2 = Array("Bob", "Carol")
f = LBound(v1)
ReDim v3(LBound(v1) To Abs(UBound(v1) - UBound(v2)))

For i = LBound(v1) To UBound(v1)
    here = False
    For j = LBound(v2) To UBound(v2)
        If InStr(1, v1(i), v2(j)) Then
            here = True
            Exit For
        End If
    Next j
    If Not here Then
        v3(f) = v1(i)
        MsgBox v3(f)
        f = f + 1
    End If
Next i
End Sub

1 Comment

Thank you, this I can follow, I know see what had to happen

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.