Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Shaun E on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Array of Arrays? 1

Status
Not open for further replies.

MrMeric

Technical User
Apr 1, 2004
48
US
Hello!

Is it possible to create an array of arrays?
I need to store an unknown amount and varying length of byte arrays.

Essentially, I would like something like this:
myArray(23,45,12,25,22,12)
myArray(12,24,25)
myArray(34,56,74,13,95,14,12,65,12)
myArray(12,34,17,73,24)
myArray(12,14,45)

Then, in a round-about kinda way, I'd like to access it like this:
debug.print myArray(1)
2
45
12
25
22
12
debug.print myArray(2)
12
24
25


Please excuse my dumb question - but I'm not that great with VB!

Thanks in advance!
 
You can create a multidimensional array. The best optin IMO however is to use dictionaries for any data structure more complex than a simple array.

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
I don't know. I don't want to know. Generally speaking, it is not a good idea to use Arrays. I would avoid them. Maybe there is another solution to your problem. What are you trying to accomplish?
 
Well, I'm using MS Access and an algorithm called Simil to search for similar customer names.
Here is the Simil code:
Code:
Option Compare Database
Option Explicit

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, source As Any, ByVal numBytes As Long)
Private LetterByteArrayOne() As Byte
Private LetterByteArrayTwo() As Byte

Public Function Simil(ByVal StringOne As String, ByVal StringTwo As String) As Double
    Dim StringOneLength As Long
    Dim StringTwoLength As Long
    Dim l As Long
    
    StringOne = UCase(StringOne)
    StringTwo = UCase(StringTwo)

    If StringOne = StringTwo Then
        Simil = 1
    Else
        StringOneLength = Len(StringOne)
        StringTwoLength = Len(StringTwo)
        If (StringOneLength = 0) Or (StringTwoLength = 0) Then
            Simil = 0
        Else
            'Find the ASCII equivalent to the letter and place it into the byte array
            ReDim LetterByteArrayOne(StringOneLength)
            ReDim LetterByteArrayTwo(StringTwoLength)
            
            CopyMemory LetterByteArrayOne(1), ByVal StringOne, StringOneLength
            CopyMemory LetterByteArrayTwo(1), ByVal StringTwo, StringTwoLength
            Simil = SubSim(1, StringOneLength, 1, StringTwoLength) / (StringOneLength + StringTwoLength) * 2
        End If
    End If
End Function

Private Function SubSim(StringOneStart As Long, StringOneEnd As Long, StringTwoStart As Long, StringTwoEnd As Long) As Long
    Dim CurrentStringOneItem As Long
    Dim CurrentStringTwoItem As Long
    Dim ns1 As Long
    Dim ns2 As Long
    Dim i As Long

    If StringOneStart > StringOneEnd Or StringTwoStart > StringTwoEnd Or StringOneStart <= 0 Or StringTwoStart <= 0 Then Exit Function

    For CurrentStringOneItem = StringOneStart To StringOneEnd
        For CurrentStringTwoItem = StringTwoStart To StringTwoEnd
            i = 0
            Do Until LetterByteArrayOne(CurrentStringOneItem + i) <> LetterByteArrayTwo(CurrentStringTwoItem + i)
                i = i + 1
                If i > SubSim Then
                    ns1 = CurrentStringOneItem
                    ns2 = CurrentStringTwoItem
                    SubSim = i
                End If
                If CurrentStringOneItem + i > StringOneEnd Or CurrentStringTwoItem + i > StringTwoEnd Then Exit Do
            Loop
        Next
    Next
    SubSim = SubSim + SubSim(ns1 + SubSim, StringOneEnd, ns2 + SubSim, StringTwoEnd)
    SubSim = SubSim + SubSim(StringOneStart, ns1 - 1, StringTwoStart, ns2 - 1)
End Function

You feed Simil two strings and it will spit out the percentage of likeness:
Code:
?Simil("stringOne","Onestring")
 0.666666666666667 
?Simil("xStringOney","yStringOnex")
 0.818181818181818 
?Simil("string one","one string")
 0.6 
?Simil("smith john","smit jon")
 0.888888888888889 
?Simil("george bush","john kerry")
 0.19047619047619 
?Simil("mahatma, gandhi","gandhi, mahatma")
 0.466666666666667

Simil works great, but for my application it's a tad slow.
I created a simple progressive linear algorithm that feeds Simil the customer names.
Code:
Public Function SimilSearch()
Dim db As DAO.Database
Dim rsSearch, rsSearchClone, rsSimilarTable As DAO.Recordset
Dim searchString, comparisonString, searchSound, comparisonSound As String
Dim SimilThreshold, stringRelevance As Double
Dim NumberFound, i, j As Integer
Dim timeStart As Double
Dim timeStop As Double
timeStart = Timer
    On Error GoTo errorhandler
    
    Set db = CurrentDb
    'Recodset we wish to search
    Set rsSearch = db.OpenRecordset("SELECT Customer.Name AS SearchField FROM Customer;", dbOpenSnapshot)
    Set rsSearchClone = rsSearch.Clone
    'Recordset we wish to place similar records into
    Set rsSimilarTable = db.OpenRecordset("SELECT * FROM SimilarStrings;", dbOpenDynaset)
    'Threshold for string comparison
    'It seems that .83 seems to be the magic number. Any higher or lower will
    'result in either too many or too few results, respectivley.
    SimilThreshold = 0.83
    
    With rsSearch
        .MoveLast
        .MoveFirst
        'Set the progress bar control max
        Me.progBar.max = .RecordCount - 1
        Do Until .EOF
            Me.progBar.value = Me.progBar.value + 1
            'Set the string we with to compare all others to for this iteration
            searchString = ![SearchField]
            'This is the loop where we compare 'searchString' to all other
            'entries within the database.
            'NOTE - This is progressive algorithm. If 'searchString' is
            'record number 15, then we start the comparison at
            'record 16.
            i = i + 1
            With rsSearchClone
                .MoveFirst
                .Move i
                Do Until .EOF
                    'stringRelevance holds the comparison percent relevancy
                    comparisonString = ![SearchField]
                    stringRelevance = Simil((searchString), (comparisonString))
                    If stringRelevance >= SimilThreshold Then
                        'For added strictness, we compare the two strings using
                        'the SoundsLike algorithm which is related to Soundex.
                        'Although the threshold was met, this dosen't mean that the
                        'two strings are completely relevant to one another.
                        searchSound = SoundsLike(searchString)
                        comparisonSound = SoundsLike(comparisonString)
                        If searchSound Like comparisonSound Then
                            If AddSimilarEntry(rsSimilarTable, searchString, comparisonString _
                                                , stringRelevance, searchSound) = False Then
                                MsgBox "Error adding new similar entry to database."
                            End If
                       End If
                    End If
                    'Move to the next comparison item
                    .MoveNext
                Loop
            End With
            'Move to the next key item
            .MoveNext
        Loop
    End With
    
    timeStop = Timer
    
    MsgBox "Total Time: " & (timeStop - timeStart)
errorhandler:
    Select Case Err.Number
        Case 0 To 3021
            Resume Next
        Case Else
            MsgBox "Error: " & Err.Number & vbCrLf & "Description: " & Err.Description
    End Select

End Function

What ends up happening, is that every customer name fed to Simil is converted into a Byte array. I believe it would be quicker to create a class that holds these byte arrays. I could then bypass this conversion when Simil is run.

Any ideas?
 
You could use a dictionary with a unique Id for the key and another dictionary for the value. The second dictionary could have two key value pairs the first would be Key = "Name" Value = "WHatever this last name is". The second item would be Key = "Bytes" Value = Byte Array for this name.

Then you could access the infromation something like this:
To get the plain text name for id xyz:
strName = oDic.Item(xyz).Item("Name")
To get the byte array for the same name
arr = oDic.Item(xyz).Item("Bytes")

[red]"... isn't sanity really just a one trick pony anyway?! I mean, all you get is one trick, rational thinking, but when you are good and crazy, oooh, oooh, oooh, the sky is the limit!" - The Tick[/red]
 
TomThumbKP - This is excellent! I can use this.
I do have one last question though...

How do I place the byte array in the dictionary? Or, are you suggesting that I have them in the dictionary as a string, such as:
arr = oDic.Item(xyz).Item("23,43,15,23")

Thanks!
 
Nevermind.

Thanks a ton! This will help a lot.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top