Pack Array

Discussion in 'AutoCAD' started by lorier, Aug 20, 2004.

  1. lorier

    lorier Guest

    Is there a simple function for 'packing' an array? That is shifting elements to the left so that all the empty elements are at the right and then redimensioning the array, so that the empties disappear.

    tia
     
    lorier, Aug 20, 2004
    #1
  2. lorier

    Ed Jobe Guest

    If you used a Collection instead of an array, you could simply delete the
    empty ones.

    --
    ----
    Ed
    ----
    elements to the left so that all the empty elements are at the right and
    then redimensioning the array, so that the empties disappear.
     
    Ed Jobe, Aug 20, 2004
    #2
  3. lorier

    Mark Propst Guest

    elements to the left so that all the empty elements are at the right and
    then redimensioning the array, so that the empties disappear.

    Hi lorier,
    I agree with Ed, that collections are much easier to use than arrays.

    and aside from that - I know you are way beyond me in terms of vb knowledge
    so this probably is
    way basic and not what you're looking for but i tried this little test as
    one way to do what you asked

    i'm sure computation wise it's a very bad way to do this and there's
    probably a cool 'real programmers way' to do it without the overhead of a
    second array

    do you ever check out microsoft.public.vb.general.discussion ng?
    they have a thousand times more traffic than this group for purely vb type
    questions and an amazing depth of knowlege on the part of their "in house
    benevolent sharing gurus"

    Sub Packarray()

    Dim fa(0 To 9) As String 'first array
    Dim sa() As String ' second array
    'load first array for testing
    Dim i As Long
    Dim sTxt As String
    sTxt = "a"
    'start with blanks
    For i = 0 To 5
    fa(i) = ""
    Next
    'put some stuff in end of array
    For i = 6 To 9
    fa(i) = sTxt
    sTxt = Chr(Asc(sTxt) + 1)
    Next i

    Debug.Print "Now first array has " & UBound(fa) + 1 & " elements"
    For i = LBound(fa) To UBound(fa)
    Debug.Print "Item " & i & ": " & fa(i)
    Next i

    'populate second array with elements that aren't "empty"
    Dim j As Long
    j = -1
    For i = LBound(fa) To UBound(fa)
    If fa(i) <> "" Then
    j = j + 1
    ReDim Preserve sa(j)
    sa(j) = fa(i)
    End If
    Next i

    Debug.Print "Now second array has " & UBound(sa) + 1 & " elements"
    For i = LBound(sa) To UBound(sa)
    Debug.Print "Item " & i & ": " & sa(i)
    Next i
    End Sub


    now granted, the items that are = "" aren't actually empty, they are strings
    of zero length so maybe you're facing a different kind of problem
    if it was a numeric array, a test for <>0 might not be right since 0 could
    either be a valid value or just an empty entry. not sure how you'd work
    with that - just depends on the program and your array and what your'e
    actually doing with it.

    well, no help i'm sure but thought I'd try to offer one idea
    good luck
    Mark
     
    Mark Propst, Aug 20, 2004
    #3
  4. You could do it in one pass by keeping track of the number of "empty"
    elements (you have to define empty yourself... zero-value?) and using that
    as the number of slots to move an item to the left.

    nE = 0 'number of empties up to this point
    UB = ubound(arr)
    LB = lbound(arr)
    for i = LB to UB
    if arr(i) = 0 then nE = nE+1 'assuming zero is empty
    'if UB cell is empty, don't try to copy into it
    if i < UB then arr(i) = arr(i + nE)
    next 'i
    redim preserve arr(LB to UB - nE)

    James


    elements to the left so that all the empty elements are at the right and
    then redimensioning the array, so that the empties disappear.
     
    James Belshan, Aug 20, 2004
    #4
  5. Hi,

    For curiosity. Why would you wish to do this ? If items in your array have
    some meaning, even the fact that they are nil would have some significance.

    --


    Laurie Comerford
    CADApps
    www.cadapps.com.au

    elements to the left so that all the empty elements are at the right and
    then redimensioning the array, so that the empties disappear.
     
    Laurie Comerford, Aug 20, 2004
    #5
  6. if i < UB then arr(i) = arr(i + nE)

    correction to my logic... you'd need to stop copying cells once you get to
    the last non-empty one in the new "packed" array. Something like

    if i < (UB - nE) then arr(i) = arr(i + nE)

    For instance, if you have an array with UB = 9, and you've counted 3 empties
    by the time you get to i=6, you don't want to try to set arr(7)= arr(7+3),
    since that would exceed the array bounds.
     
    James Belshan, Aug 20, 2004
    #6
  7. lorier

    lorier Guest

    i have a string like this "1. abc def 21. abc def" and what I want is "abc def abc def" so i 'split' to make an array and I thought i could delete whats in every third element and thus I needed to 'pack' it. The word 'pack' is a carryover from a function in clipper. Thanks for everyone's input, i'm still trying to decide on the best way. Its seems that i'll just have to use a temporary array.
     
    lorier, Aug 21, 2004
    #7
  8. i have a string like this "1. abc def 21. abc def" and what I want
    is "abc def abc def" so i 'split' to ...

    Question... will you know that it's every third value that you don't want,
    or do you want to filter out all the numeric items?

    If the result you really want is a new string, you could loop through the
    SPLIT array, and re-concatenate each element of the array, skipping the ones
    you don't want. No second array required. If it's every third one that you
    want to delete, you would test by:
    If i Mod 3 = 0 then... '(if SPLIT result is 0-based)
    If (i-1) Mod 3 = 0 then .... '(if 1-based)

    If it's numeric items that you want to delete, then:
    If Not IsNumeric(array(i)) then newString = newString & array(i)


    HTH,
    James
     
    James Belshan, Aug 21, 2004
    #8
  9. lorier

    bcoward Guest

    Lorier,

    Being familiar with the 1992 days of Clipper I understand how you get to arrays. As you now clarify what you want to do with the new ideas you've received I'll add something that might help you with the array you have after Split().

    Once you've used Split() you have a one dimensional array that contain a specific number of substrings. Each substring will contain a delimiter. If you ommitted this parameter your delimiter is " " or chr(32). When in this situation I use the following function if I know which index or substring I want to return. If this isn't want you want I also have the array manipulation routines if you want to move that way. Just let us know.

    Example of using the function:

    ObjAttRef.TextString = MyAcad.GetDelimitedWord(frmTitleBlockInfo.txtWrkOrdr.Text, 1, ",")

    Function:

    Public Function GetDelimitedWord(strIn As String, ByVal lngIndex As Long, chrDelimit As String) As String

    ' Comments : Returns word intIndex in delimited string strIn
    ' Parameters: strIn - String to search
    ' lngIndex - Word position to find
    ' chrDelimit - Character used as the delimter
    ' Returns : nth word
    '

    Dim lngCounter As Long
    Dim lngStartPos As Long
    Dim lngEndPos As Long

    On Error GoTo Err_Handler

    ' Set initial values
    lngCounter = 1
    lngStartPos = 1

    ' Count to the specified index
    For lngCounter = 2 To lngIndex
    ' Get the new starting position
    lngStartPos = InStr(lngStartPos, strIn, chrDelimit) + 1
    Next lngCounter

    ' Determine the ending position
    lngEndPos = InStr(lngStartPos, strIn, chrDelimit) - 1
    ' Ending position can't be less than 1
    If lngEndPos <= 0 Then
    lngEndPos = Len(strIn)
    End If

    ' Pull the word out and return it
    GetDelimitedWord = Mid$(strIn, lngStartPos, lngEndPos - lngStartPos + 1)

    Exit_Here:
    Exit Function

    Err_Handler:
    MsgBox "Error: " & Err.Number & ". " & Err.Description, , _
    "GetDelimitedWord"
    Resume Exit_Here

    Good luck, if you change your direction just ask, and someone will build it.

    Regards,

    Bob Coward
    CADS, Inc

    800-366-0946
     
    bcoward, Aug 21, 2004
    #9
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.