Home > Enterprise >  Swift array move function doesn't behave as you would expect - why?
Swift array move function doesn't behave as you would expect - why?

Time:09-25

Recently Swift has a new method called move for Arrays. We can use it to tie in with Swiftui list drag and drop list moves. My challenge is that I don't understand how it works standalone and the docs in Apple are sparse about this. Here's a weird behavior I've noticed when I just play with this function.

var array = ["a", "b" ,"c", "d"]
print("before \(array)\n")
array = ["a", "b" ,"c", "d"]
array.move(fromOffsets: IndexSet(integer: 2), toOffset: 1)
print("after 2 -> 1 \(array)")
        
array = ["a", "b" ,"c", "d"]
array.move(fromOffsets: IndexSet(integer: 1), toOffset: 2)
print("after 1 -> 2 \(array)")

array = ["a", "b" ,"c", "d"]
array.move(fromOffsets: IndexSet(integer: 2), toOffset: 2)
print("after 2 -> 2 \(array)")

Results are:

after 2 -> 1 ["a", "c", "b", "d"]

after 1 -> 2 ["a", "b", "c", "d"]

after 2 -> 2 ["a", "b", "c", "d"]

I'm super confused about the 1->2 result ... how's that not change the array! It should be the same as the 2->1 shouldn't it?

Please help me understand.

CodePudding user response:

my understanding of the move operation is:

Moves all the elements at the specified offsets to the specified destination offset, preserving ordering.

The move is to just before destination, so the results you get are correct.

CodePudding user response:

I spend some time making ASCII art diagrams, so let's not put that time to waste.

Conceptually, I think of it as:

  • index points to the actual element
  • offset is the number of spaces travelled from the start of the array; essentially pointing at the gap between the elements

Thus, the algorithm is to:

  • get the item at specified index
  • determine the target offset (based on the array as it stands)
  • move that item into that offset

So, with your use cases:

["a", "b", "c", "d"]: moving from index 2 to offset 1: ["a", "c", "b", "d"]

|a|b|c|d| |a|b|c|d|
     v      ^
     |      |
      ------ 

["a", "b", "c", "d"]: moving from index 1 to offset 2: ["a", "b", "c", "d"]

|a|b|c|d| |a|b|c|d|
   v          ^
   |          |
    ---------- 

["a", "b", "c", "d"]: moving from index 2 to offset 2: ["a", "b", "c", "d"]

|a|b|c|d| |a|b|c|d|
     v        ^
     |        |
      -------- 

As you can see, nominating an offset that would place the element adjacent to itself would result in no apparent change to the array.

  • Related