Reordering items in array

What is the best way to reorder items in an array. I know you could use the Insert and Remove functions but are there any more powerful functions to help me reorder my array items. Please could somebody give me a script for moving multiple items in an array to specific places. What I mean, is I want to move multiple array items to the same place. Do I need to backup the current array items or what? For example, I want to just say something like:

dim reorderItemIndexes() as integer
reorderItemIndexes.append 1
reorderItemIndexes.append 2
newIndex = 7
'first parameter is the index of the items to reorder, second parameter is the new index to squeeze the array items with the index of reorderItemIndexes in front of:
array1.Reorder(reorderItemIndexes,newIndex)

'It should move the array items from 1,2 to 7,8 (I think, unless I have made human error)

Thanks

Look up Array.SortWith.

How would I go about reordering an array though. Examples?

Thanks

[quote=52275:@Oliver Scott-Brown]How would I go about reordering an array though. Examples?

Thanks[/quote]
Btw I think I understand what SortWith does but I feel like I need an example to work out how to reorder array items like this.

Thanks

SortWith requires that both array are the same size. As long as you put the names, emails, and phone number into the arrays in order, you can then have:

[code]Names(10) as string
PhoneNumbers(10) as string
Emails(10) as string

Names.SortWith(PhoneNumbers,Emails)[/code]

This will alphabetically sort the names, and sort the phone numbers and emails based on where the names were moved to. The indexes of each will still match their associated info in the other arrays, so you can show info easily with:

for i as integer=0 to ubound(names) msgbox names(i)+" "phoneNumbers(i)+" "+emails(i) next

For manually rearranging an array, you’ll have to get a reference to the item, remove it from the array, and insert it back in where you want it.

[quote=52293:@Tom Iwaniec]SortWith requires that both array are the same size. As long as you put the names, emails, and phone number into the arrays in order, you can then have:

[code]Names(10) as string
PhoneNumbers(10) as string
Emails(10) as string

Names.SortWith(PhoneNumbers,Emails)[/code]

This will alphabetically sort the names, and sort the phone numbers and emails based on where the names were moved to. The indexes of each will still match their associated info in the other arrays, so you can show info easily with:

for i as integer=0 to ubound(names) msgbox names(i)+" "phoneNumbers(i)+" "+emails(i) next

For manually rearranging an array, you’ll have to get a reference to the item, remove it from the array, and insert it back in where you want it.[/quote]
Thanks, I will give it a try.

You can also reorder in any arbitrary fashion by creating an array that is the same size as your target array(s), filling it in with indexes, and then using SortWith to reorder the target arrays. So let’s say you have a targetArr( 9 ) filled with data.

dim indexArr( 9 ) as integer = Array( 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 )
indexArr.SortWith targetArr
// Now targetArr's order has been flipped

Sorry but my mind is boggled on how to do this. Please could someone give me an example, that does not just show what SortWith does because I understand that. I just cannot get my brain around the problem I am trying to solve. If you are giving an example, please make sure it is not too vague otherwise I just get more confused. If you are providing me with an example, please make sure it shows:

1)How I can declare the array, put the values of the desired indexes in their (which I believe is what Kem showed me there).
2)How I can move the items in the array using the indexes array

I do not know what to do with either of the arrays.

Thankyou all

OK so you have an array already & want to reorder it
Lets assume you have an array of strings, called Names, since I really don’t know what you do have
And you want to move some items, items 1 and 2 in Name, to new positions 7 and 8

So lets do something manual JUST so you can copy paste into a small sample

[code]dim names() as string
names.append “A”
names.append “B”
names.append “C”
names.append “D”
names.append “E”
names.append “F”
names.append “G”
names.append “H”
names.append “I”

dim reorderItemIndexes() as integer
reorderItemIndexes.append 0
reorderItemIndexes.append 7
reorderItemIndexes.append 8
reorderItemIndexes.append 1
reorderItemIndexes.append 2
reorderItemIndexes.append 3
reorderItemIndexes.append 4
reorderItemIndexes.append 5
reorderItemIndexes.append 6

break // examine the contents of both arrays in the debugger here

reorderItemIndexes.sortwith names

break // examine the contents of both arrays in the debugger here
[/code]

ok so what the heck is going on ?
reorderitemindexes must be the same “length” as names
One item in reorderitemindexes matches one item in names
Then when we sort the reorderitemindexes the runtime keeps the rows in names matched up with the row in reorderItemIndexes

But now the reorderItemIndexes is sorted in ascending order and the matching rows in Names have moved

And since it sorts reorderitemindexes numerically what you get is the items in NAMES(1) moved to be item in NAMES(7) and names(2) moved to NAMES(8)

Try it in a small sample & see
Very handy

Here is some code I haven’t tested that should do the job you’re seeking. You already have a string array that you want to reorder by moving a range defined by startIndex and count to another location within the array. In your example, you’d call it as MoveRange( array1, 1, 2, 7 ), meaning, take the items at index 1 and 2 and move them to index 7, shifting everything else in the array up. In this code, it won’t matter if array1 has a Ubound of 8 or 8000. However, if Ubound is less than 8, you will get unexpected results.

Sub MoveRange (arr() As String, startIndex As Integer, count As Integer, destinationIndex As Integer)
  dim indexArr() as Integer // The array that will determine the final order
  redim indexArr( arr.Ubound ) // Same size as the string array

  dim buffer as integer = 10
  while buffer <= count
    buffer = buffer * 10
  wend

  for i as integer = 0 to indexArr.Ubound
    indexArr( i ) = i * buffer // Fill in the index array as 0, 10, 20, ...
  next i

  // Adjust the indexes
  dim lastIndex as integer = count - 1
  for i as integer = 0 to lastIndex
    indexArr( startIndex + i ) = ( destinationIndex * buffer ) + i + 1 // The new indexes will be 71, 72
  next i

  // At this point, the index array will look like 0, 71, 72, 30, 40, 50, 60, 70, 80, 90, …

  indexArr.SortWith( arr ) // Sort the indexArr and the string array along with it

  // Now the indexArr will be 0, 30, 40, 50, 60, 70, 71, 72, 80, 90, …
  // and the elements in arr will match that order.
End Sub

Very sorry to say this and use your time but my mind is still tangled and confused. I shall explain what I am trying to do in more detail.

I am using the FGThumbnailClass (https://bitbucket.org/garrypettet/fgthumbnailcanvas) for thumbnails

What I am trying to do is move the thumbnails left or right. I can easily move a single thumbnail but I don’t know how I could move multiple at once.

For example;

Thanks, sorry for the rubbing out of text (did it to prevent confusion on what I am trying to achieve)

https://xojo.io/03ef016dcde7

[quote=52336:@Kem Tekinay]Here is some code I haven’t tested that should do the job you’re seeking. You already have a string array that you want to reorder by moving a range defined by startIndex and count to another location within the array. In your example, you’d call it as MoveRange( array1, 1, 2, 7 ), meaning, take the items at index 1 and 2 and move them to index 7, shifting everything else in the array up. In this code, it won’t matter if array1 has a Ubound of 8 or 8000. However, if Ubound is less than 8, you will get unexpected results.

[code]
Sub MoveRange (arr() As String, startIndex As Integer, count As Integer, destinationIndex As Integer)
dim indexArr() as Integer // The array that will determine the final order
redim indexArr( arr.Ubound ) // Same size as the string array

dim buffer as integer = 10
while buffer <= count
buffer = buffer * 10
wend

for i as integer = 0 to indexArr.Ubound
indexArr( i ) = i * buffer // Fill in the index array as 0, 10, 20, …
next i

// Adjust the indexes
dim lastIndex as integer = count - 1
for i as integer = 0 to lastIndex
indexArr( startIndex + i ) = ( destinationIndex * buffer ) + i + 1 // The new indexes will be 71, 72
next i

// At this point, the index array will look like 0, 71, 72, 30, 40, 50, 60, 70, 80, 90, …

indexArr.SortWith( arr ) // Sort the indexArr and the string array along with it

// Now the indexArr will be 0, 30, 40, 50, 60, 70, 71, 72, 80, 90, …
// and the elements in arr will match that order.
End Sub
[/code][/quote]
Wow, don’t know if this works with what I am trying to do and the data types I am using but if this code works then excellent. Thankyou for your amazing help. I love how you sent me a method to simplify things to the extreme, good work!!

Change the declaration of arr from string to your data type and it will work the same way.

Do you want to be able to move two non-adjacent items? If so your code will be more complicated because values in between selected items won’t want to be moved with the selected items.

I am happy with adjacent items for now, but in the future I may not to move forward with the UI. THANKS

Very nice solution, Kem!

If the icons you want to move right aren’t right next to each other where should they go? I mean do they group or stay seperated with other icons moving through them or something else? Can you move them only 1 space at a time or 2 or move all to the end?

SortWith can do this and maybe easier, I need to study Kems code more, but I’d take a simple brute force approach and copy out the items to be moved to a temporary array, remove them, then reinsert in the correct positions. What the correct positions are depends on those questions.

This untested code will move the first selected item a certain amount and group all other selected items after it.
(FGItems have a ‘isSelected’ property which are the ones to be moved)

[code]Sub moveSelected(arr() As FGItem, moveAmount As integer)

//index of first selected item, init -1 to signify it’s unset
dim firstSelIdx As integer = -1

//temporary array for selected items
dim temp() As FGItem

for i As integer = 0 to arr.Ubound //loop over array
if arr(i).isSelected then //if this item is selected…
temp.Append arr(i) //store it in temp
if firstSelIdx = -1 then firstSelIdx = i //record if this is the first one
end
next

for i As integer = arr.Ubound downto 0 //loop over again (going downwards because removing)
if arr(i).isSelected then arr.Remove(i) //remove selected items (still stored in temp)
next

//now arr is devoid of selected items, temp has them and firstSelIdx is set

if firstSelIdx = -1 then return //no items to move, skip out

//calculate position to start reinserting items
dim insertPos As integer = firstSelIdx + moveAmount

//fix insertPos to valid index
if insertPos < 0 then insertPos = 0
if insertPos > arr.Ubound + 1 then insertPos = arr.Ubound + 1

for i As integer = 0 to temp.Ubound //now insert all together
arr.insert(insertPos + i, temp(i))
next

End Sub
[/code]

[quote=52357:@Will Shank]If the icons you want to move right aren’t right next to each other where should they go? I mean do they group or stay seperated with other icons moving through them or something else? Can you move them only 1 space at a time or 2 or move all to the end?

SortWith can do this and maybe easier, I need to study Kems code more, but I’d take a simple brute force approach and copy out the items to be moved to a temporary array, remove them, then reinsert in the correct positions. What the correct positions are depends on those questions.

This untested code will move the first selected item a certain amount and group all other selected items after it.
(FGItems have a ‘isSelected’ property which are the ones to be moved)

[code]Sub moveSelected(arr() As FGItem, moveAmount As integer)

//index of first selected item, init -1 to signify it’s unset
dim firstSelIdx As integer = -1

//temporary array for selected items
dim temp() As FGItem

for i As integer = 0 to arr.Ubound //loop over array
if arr(i).isSelected then //if this item is selected…
temp.Append arr(i) //store it in temp
if firstSelIdx = -1 then firstSelIdx = i //record if this is the first one
end
next

for i As integer = arr.Ubound downto 0 //loop over again (going downwards because removing)
if arr(i).isSelected then arr.Remove(i) //remove selected items (still stored in temp)
next

//now arr is devoid of selected items, temp has them and firstSelIdx is set

if firstSelIdx = -1 then return //no items to move, skip out

//calculate position to start reinserting items
dim insertPos As integer = firstSelIdx + moveAmount

//fix insertPos to valid index
if insertPos < 0 then insertPos = 0
if insertPos > arr.Ubound + 1 then insertPos = arr.Ubound + 1

for i As integer = 0 to temp.Ubound //now insert all together
arr.insert(insertPos + i, temp(i))
next

End Sub
[/code][/quote]
Cool thanks.