Search code examples
arraysswiftsortingenumerate

Swift For loop Enumeration in Sort differs


Im trying to manual sort on the below array.

The issue here is, the result varies while reading the item from the "for-loop enumuration" (noted as //(2)) verses reading it as a subscript (noted as //(1)). It could be a minor issue hiding behind my eye. Appreciate your time.

var mySortArray : Array<Int> = []

mySortArray = [1,5,3,3,21,11,2]

for (itemX,X) in mySortArray.enumerated() {

  for (itemY,Y) in  mySortArray.enumerated() {

       // if  mySortArray[itemX] <  mySortArray[itemY] // (1)
        if X < Y  // (2)
        {
            //Swap the position of item in the array
                mySortArray.swapAt(itemX, itemY)
        }

    }
}

print(mySortArray)

// Prints [1, 2, 3, 3, 5, 11, 21]  ( for condition // (1))
// Prints [2, 1, 3, 5, 11, 3, 21]  ( for condition // (2))

mySortArray = [1,5,3,3,21,11,2]
print("Actual Sort Order : \(mySortArray.sorted())")
// Prints Actual Sort Order : [1, 2, 3, 3, 5, 11, 21]

Solution

  • The problem here is that the function .enumerated() returns a new sequence and iterates that. Think of it as a new array.

    So, you are working with 3 different arrays here.

    You have an unsorted array that you want to fix. Lets call this the w ("working array") and then you have you array x and array y.

    So, w is [1,5,3,3,21,11,2], x and y are effectively the same as w at the beginning.

    Now you get your first two values that need to swap...

    valueX is at index 1 of x (5). valueY is at index 2 of y (3).

    And you swap them... in w.

    So now w is [1,3,5,3,21,11,2] but x and y are unchanged.

    So now you indexes are being thrown off. You are comparing items in x with items in y and then swapping them in we which is completely different.

    You need to work with one array the whole time.

    Of course... there is also the issue that your function is currently very slow. O(n^2) and there are much more efficient ways of sorting.

    If you are doing this as an exercise in learning how to write sort algorithms then keep going. If not you should really be using the .sort() function.

    Really what you want to be doing is not using .enumerated() at all. Just use ints to get (and swap) values in w.

    i.e. something like

    for indexX in 0..<w.count {
        for indexY in indexX..<w.count {
            // do some comparison stuff.
            // do some swapping stuff.
        }
    }