Results 1 to 39 of 39

Thread: Compacting arrays

  1. #1

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276

    Compacting arrays

    Awight people!

    Right, I have the worlds biggest stinker of an array that certain elements will become redundant over time. These elements will have a flag saying they're no good, but I want to compact the array to remove the elements.

    Does anyone have any decent / fast methods of doing this?
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  2. #2
    DaoK
    Guest
    i can make you a Function, give me 30 minutes ok, but in few word you have to do a loop to check if the array have the value if not add it on the tempo... if the array is big it will take few second...

  3. #3
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Move all the elements that are bad to the back of the array, then use ReDim
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  4. #4

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Whoa, Daok - I can do that.

    The only thing is the array is a UDT with a bog load of properties that I didn't want to have to set manually....

    Attached is the UDT...

    VB Code:
    1. Type unitTemp
    2.         XC As Integer
    3.         YC As Integer
    4.         weapon(4) As Byte
    5.         ammo(4) As ammotemp
    6.         AutoModel As Byte
    7.         Speed As Single
    8.         CurrShields As Single
    9.         CurrArmour As Single
    10.         MaxArmour As Single
    11.         torso As Integer
    12.         reactor As Byte
    13.         Standingcharge As Single
    14.         MaxEnergyDrain As Integer
    15.         EnergyUsed As Single
    16.         Weight As Single
    17.         Status As Boolean
    18.         Chip(3) As Byte
    19.         ChassisType As Byte
    20.         SheildGenerator As Byte
    21.         ArmourType As Byte
    22.         Name As String
    23.         DestXC As Integer
    24.         DestYC As Integer
    25.         TurnComplete As Boolean
    26.         SpeedRemaining As Single
    27.         EnergyUsedPerMove As Single
    28.         WeaponFireState(4) As firestatetemp
    29.         ViewRadius As Byte
    30.         options As String
    31.         ProcCost As Single
    32.         GraphicID As Long
    33.         Autopilot As Boolean
    34.         Maturity As Integer
    35.         MatStage As Byte
    36.         HomeX As Integer
    37.         HomeY As Integer
    38.         ChanceOfSettleDown As Byte
    39.         MonsterType As Byte
    40.         Read(7) As Boolean
    41.         Might As Single
    42.     End Type
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  5. #5

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    As you can see there are quite a few individual wotsits that I have to move for each unit.

    Can I move an arrays element without transferring the data items individually?

    If so, could you point me in the right direction?
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  6. #6
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    How's this

    VB Code:
    1. Option Explicit
    2.  
    3. Private myArray() As argType
    4. Private Type argType
    5.     a As Long
    6.     b As String
    7.     c As Integer
    8.     d As Currency
    9.     exists As Boolean
    10. End Type
    11.  
    12.  
    13. Private Sub Form_Load()
    14.     Dim i As Long
    15.     ReDim myArray(9999)
    16.     For i = 0 To 9999
    17.         myArray(i).exists = Not ((i Mod 100) = 0)
    18.     Next
    19.     ReDim Preserve myArray(UBound(myArray) - putNonExistantElementsToBack(myArray))
    20. End Sub
    21.  
    22. Private Function putNonExistantElementsToBack(ByRef myArr() As argType) As Long
    23.     Dim i As Long, j As Long, tempArr() As argType: ReDim tempArr(UBound(myArr))
    24.     For i = 0 To UBound(myArr)
    25.         If Not myArr(i).exists Then
    26.             tempArr(UBound(myArr) - j) = myArr(i)
    27.             j = j + 1
    28.         Else
    29.             tempArr(i) = myArr(i)
    30.         End If
    31.     Next
    32.     myArr = tempArr
    33.     putNonExistantElementsToBack = j
    34. End Function
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  7. #7

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Ummm, what about all the array elements?
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  8. #8
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    All bad array elements are put to the back of the array.
    Then you call ReDim to cut the bad part off.
    Ya folly ?
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  9. #9

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Ahhhh, the function takes the input as the type of the wotsit.

    I didn't know you could do that.

    Hehehehe, aren't I thick!

    I understood the principle but wasn't sure how it would transfer all the variables in the type.

    That's cool - cheers Plend!
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  10. #10
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    No probs. Though there is an easier approach.
    Make a dynamic array. Loop through the first array.
    For each index that does exist/is good, redim preserve the other array 1 bigger and put that index into it.

    That'd be much easier though slower. But it'd be much easy to debug and what not...
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  11. #11

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    I think that's what Daok was suggesting.

    Well, as long as this method of yours works then I'll have no call to firebomb your house...
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  12. #12
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    I had better test it so
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  13. #13

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Hang about.

    Isn't this code of your flawed?

    I notice that it's putting the bad ones at the back moving them progressively forward, but it's putting the good ones back in the same position.

    Or am I wrong?
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  14. #14
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    You're wrong. i <> j

    Anyway, use this instead ;

    VB Code:
    1. Option Explicit
    2.  
    3. Private myArray() As argType
    4. Private Type argType
    5.     a As Long
    6.     b As String
    7.     c As Integer
    8.     d As Currency
    9.     exists As Boolean
    10. End Type
    11.  
    12.  
    13. Private Sub Form_Load()
    14.     Dim i As Long
    15.     ReDim myArray(9999)
    16.     For i = 0 To 9999
    17.         myArray(i).exists = Not ((i Mod 100) = 0)
    18.     Next
    19.    
    20.     Dim tempArr() As argType
    21.     ReDim tempArr(0)
    22.     For i = 0 To UBound(myArray)
    23.         If myArray(i).exists Then
    24.             tempArr(UBound(tempArr)) = myArray(i)
    25.             ReDim Preserve tempArr(UBound(tempArr) + 1)
    26.         End If
    27.     Next
    28.    
    29.     ReDim pyarray(UBound(tempArr))
    30.     myArray = tempArr
    31. End Sub
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  15. #15

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    I know I<>J and I don't think I'm wrong.

    The if doesn't exist bit is right, but the does exist bit is wrong.

    Run through it on paper with an array of 10 items if you don't believe me.

    Anyways, now I know you can pass UDT arrays to functions, I'm laughing anyway - I can write it myself now, I just didn't know you could do that.

    Ta muchly Plend!
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  16. #16
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Bah I just wrote the thing in about 2 minutes while eating a bigmac
    The basic idea for the first algorithm is sound... oh yeah I see. I should add in another counter, k, and count the number of good items. Good items go into tempArr(k) and bad items into tempArr(UBound(myArr) - j)

    Pffft. Pretty damn close with no testing I'd say though
    I'd stick with the second example I posted anyway. That seems to me to be the easiest way of doing it ... oh and I tested it too
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  17. #17

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Yep, you needed another counter.

    I'd already amended the code before I told you, but your second code seems a bit neater.

    How was the BigMac? And only one? You need at least two and some fried for a proper snack!
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  18. #18
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Yeah just the one. I didn't want to seem greedy
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  19. #19
    Hyperactive Member
    Join Date
    Jul 2000
    Location
    Halifax,UK
    Posts
    274
    why not use a collection? then the collection resizes automatically and gets rid of them when you want?
    VB6 VS2005

  20. #20
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Arrays are easier (and faster) to work with
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  21. #21

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Definately so, and speed is an issue here.

    Also Sentience is now over 28500 lines of code - I will show my arse if I'm going to chance something so fundamental at this stage....

    PS - Plend, when do we next get one of those super furry bug lists off you....
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  22. #22
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Whenever you ask
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  23. #23

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Plend,

    Please can we have one of those super furry bug lists off you?

    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  24. #24
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Of course
    I'll do one up tonight when I get home
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  25. #25

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Awwww, what a hero!!!

    A tip for you - on the main game screen (when you can see units and buildings) press "p".

    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  26. #26
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    I've a small list already. Will post in g&g forum
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  27. #27
    jim mcnamara
    Guest
    Have you considered using sparse arrays? Sparse arrays are virtual arrays that are huge, but many of the elements don't exist in physical memory. The elements may come and go dynamically

    Sample .CLS file attached.


    From:
    http://www.softcircuits.com/sw_vbsrc.htm

  28. #28
    jim mcnamara
    Guest
    The idea is that you read thru the array and delete the element.
    You don't have to copy or move elements around.

  29. #29
    PowerPoster beachbum's Avatar
    Join Date
    Jul 2001
    Location
    Wollongong, NSW, Australia
    Posts
    2,274
    We all know that Jamie is a bit of a half ass hack at programming and his method sux lol

    Arbiter, redim preserve is slow and so should be used as little as possible. Modify the Irish git's form load code (the second half) for something like this..
    VB Code:
    1. lCounter = -1
    2.     ReDim tempArr(UBound(myArray))
    3.     For i = 0 To UBound(myArray)
    4.         If myArray(i).exists Then
    5.             lCounter = lCounter + 1
    6.             tempArr(lCounter) = myArray(i)
    7.         End If
    8.     Next
    9.     ReDim Preserve tempArr(lCounter)
    10.     ReDim myArray(lCounter)
    11.     myArray = tempArr
    Good to have you and ur barnyard animals back Jamie
    Stuart Laidlaw
    Brightspark Financial Software
    http://www.gstsmartbook.com

  30. #30
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Fack awf

    'aint nutin wrong with Redim Preserve when being used to simply chop off the end of an array. I stand by my code
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  31. #31
    PowerPoster beachbum's Avatar
    Join Date
    Jul 2001
    Location
    Wollongong, NSW, Australia
    Posts
    2,274
    Originally posted by plenderj
    'aint nutin wrong with Redim Preserve when being used to simply chop off the end of an array. I stand by my code
    yep sure anything u say!
    with 99999 array items running on my Vic 20 the results were...

    Code:
    Irish Git 1400
    Me 818
    Irish Git 1315
    Me 869
    Irish Git 1331
    Me 828
    Irish Git 1379
    Me 854
    Irish Git 1459
    Me 830
    Irish Git 1438
    Me 793
    Stuart Laidlaw
    Brightspark Financial Software
    http://www.gstsmartbook.com

  32. #32
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    You just hang on a minute there .... *mutter*mutter*
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  33. #33
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Ok. Average times taken after 10 iterations of each ;

    jamie; 459
    stuart; 348


    But did you test yours yet ?
    ie. does it do the job ?

    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetTickCount Lib "kernel32" () As Long
    4.  
    5. Private myArray() As argType
    6. Private Type argType
    7.     a As Long
    8.     b As String
    9.     c As Integer
    10.     d As Currency
    11.     exists As Boolean
    12. End Type
    13.  
    14.  
    15. Private Function jamie() As Long
    16.     Dim tempTime As Long, elapsed As Long, n As Long, i As Long
    17.     Dim tempArr() As argType
    18.     For n = 0 To 9
    19.         tempTime = GetTickCount
    20.         ReDim myArray(99999)
    21.         For i = 0 To 99999
    22.             myArray(i).exists = Not ((i Mod 100) = 0)
    23.         Next
    24.         ReDim tempArr(0)
    25.         For i = 0 To UBound(myArray)
    26.             If myArray(i).exists Then
    27.                 tempArr(UBound(tempArr)) = myArray(i)
    28.                 ReDim Preserve tempArr(UBound(tempArr) + 1)
    29.             End If
    30.         Next
    31.         ReDim pyarray(UBound(tempArr))
    32.         myArray = tempArr
    33.         tempTime = GetTickCount - tempTime
    34.         elapsed = elapsed + tempTime
    35.     Next
    36.     jamie = (elapsed / 10)
    37. End Function
    38.  
    39. Private Function stuart() As Long
    40.     Dim tempTime As Long, elapsed As Long, n As Long, i As Long
    41.     Dim tempArr() As argType, lCounter As Long
    42.     For n = 0 To 9
    43.         tempTime = GetTickCount
    44.         ReDim myArray(99999)
    45.         For i = 0 To 99999
    46.             myArray(i).exists = Not ((i Mod 100) = 0)
    47.         Next
    48.         lCounter = -1
    49.         ReDim tempArr(UBound(myArray))
    50.         For i = 0 To UBound(myArray)
    51.             If myArray(i).exists Then
    52.                 lCounter = lCounter + 1
    53.                 tempArr(lCounter) = myArray(i)
    54.             End If
    55.         Next
    56.         ReDim Preserve tempArr(lCounter)
    57.         ReDim myArray(lCounter)
    58.         myArray = tempArr
    59.         tempTime = GetTickCount - tempTime
    60.         elapsed = elapsed + tempTime
    61.     Next
    62.     stuart = (elapsed / 10)
    63. End Function
    64.  
    65. Private Sub Form_Load()
    66.     MsgBox "Times taken : " & vbCrLf & vbCrLf & _
    67.             "Jamie's Method  : " & jamie & vbCrLf & _
    68.             "Stuart's Method : " & stuart, vbInformation
    69. End Sub
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  34. #34
    PowerPoster beachbum's Avatar
    Join Date
    Jul 2001
    Location
    Wollongong, NSW, Australia
    Posts
    2,274
    Test? what's that word mean?
    yeah it should work.. concept is just this...
    Code:
    A | 0 | 0 | 1 | 0 | 1 | 0 | 'original array 6 with 2 to remove
    
    B | X | X | X | X | X | X | 'new array set to same size
    
    B | 0 | 0 | 0 | 0 | X | X | 'copy correct entries to new array
    
    'keeping count of correct entries resize the new array
    B | 0 | 0 | 0 | 0 | 
    A | X | X | X | X | 'then resize original array
    
    and copy across
    A | 0 | 0 | 0 | 0 |
    regards
    Stuart
    Stuart Laidlaw
    Brightspark Financial Software
    http://www.gstsmartbook.com

  35. #35
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    "should work" ... "concept" .... bah stuart
    I bet your code doesnt even work. I'll test it hang on.
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  36. #36
    PowerPoster beachbum's Avatar
    Join Date
    Jul 2001
    Location
    Wollongong, NSW, Australia
    Posts
    2,274
    Geesh it was only ur code rearranged.. cant see how ur rock solid code can go wrong with such a minor adjustment
    Stuart Laidlaw
    Brightspark Financial Software
    http://www.gstsmartbook.com

  37. #37
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Pfft.
    Your code works

    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetTickCount Lib "kernel32" () As Long
    4.  
    5. Private Type argType
    6.     a As Long
    7.     b As String
    8.     c As Integer
    9.     d As Currency
    10.     exists As Boolean
    11. End Type
    12.  
    13. Private Sub form_load()
    14.  
    15.     Dim i As Long
    16.     Dim tempArr1() As argType, myArray1() As argType
    17.     Dim tempArr2() As argType, myArray2() As argType
    18.        
    19.     ReDim myArray1(99999)
    20.     For i = 0 To 99999
    21.         myArray1(i).exists = Not ((i Mod 100) = 0)
    22.         myArray1(i).a = i
    23.     Next
    24.     ReDim tempArr1(0)
    25.     For i = 0 To UBound(myArray1)
    26.         If myArray1(i).exists Then
    27.             tempArr1(UBound(tempArr1)) = myArray1(i)
    28.             ReDim Preserve tempArr1(UBound(tempArr1) + 1)
    29.         End If
    30.     Next
    31.     ReDim myArray1(UBound(tempArr1))
    32.     myArray1 = tempArr1
    33.        
    34.     Dim lCounter As Long
    35.     ReDim myArray2(99999)
    36.     For i = 0 To 99999
    37.         myArray2(i).exists = Not ((i Mod 100) = 0)
    38.         myArray2(i).a = i
    39.     Next
    40.     lCounter = -1
    41.     ReDim tempArr2(UBound(myArray2))
    42.     For i = 0 To UBound(myArray2)
    43.         If myArray2(i).exists Then
    44.             lCounter = lCounter + 1
    45.             tempArr2(lCounter) = myArray2(i)
    46.         End If
    47.     Next
    48.     ReDim Preserve tempArr2(lCounter)
    49.     ReDim myArray2(lCounter)
    50.     myArray2 = tempArr2
    51.    
    52.     MsgBox "Ubound of both arrays : " & UBound(myArray1) & "," & UBound(myArray2)
    53.     For i = 0 To UBound(myArray1)
    54.         If Not (myArray1(i).a = myArray2(i).a) Then
    55.             MsgBox "Ack!"
    56.         End If
    57.     Next
    58. End Sub
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

  38. #38

    Thread Starter
    PowerPoster Arbiter's Avatar
    Join Date
    Sep 2000
    Location
    Manchester
    Posts
    2,276
    Children, children, play nice.

    Oh never mind.

    I wrote my own anyway using Plends as a base.

    I must say, it did come out looking more like Stuarts though - I dimmed the temp array to the same size as the and then chopped it down at the end rather than increasing its size by one every time.

    Not that it matters really, as long as it works...
    Gentile or Jew,
    O you who turn the wheel and look to windward,
    Consider Phlebas, who was once handsome and tall as you...

  39. #39
    Retired VBF Adm1nistrator plenderj's Avatar
    Join Date
    Jan 2001
    Location
    Dublin, Ireland
    Posts
    10,359
    Yeah 'tis a bit stupid to redim all the way through
    Microsoft MVP : Visual Developer - Visual Basic [2004-2005]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width