Saltar al contenido →

Ordenar un array en Swift con sort o sortInPlace

Como desarrolladores nos encontramos día sí día también con estructuras de tipo Array o Set con las que tenemos que trabajar, y una de las operaciones que más se hacen con ellas es ordenarlas.

Para ello la Swift Standar Library tiene dos métodos que nos hacen esta tarea mucho más fácil, se trata de sort y sortInPlace definidas en el protocolo MutableCollectionType. Los dos hacen los mismo, pero existe una diferencia, y es que mientras sort devuelve un nuevo array ordenado a partir del original, sortInPlace ordena el propio array sin necesidad de crear uno nuevo.

let fixed_array: [Int] = [ 2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
var mutable_array: [Int] =  [ 2, 8, 10, 3, 6, 5, 4, 7, 1, 9]

let new_fixed_array = fixed_array.sort()
mutable_array.sortInPlace()

print("> mutable: \(mutable_array.descriptionWithSeparator(", "))")
print("> fixed: \(fixed_array.descriptionWithSeparator(", "))")
print("> new fixed: \(new_fixed_array.descriptionWithSeparator(", "))")

// En la consola de depuración veremos...
// > mutable: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
// > fixed: 2, 1, 4, 3, 6, 5, 8, 7, 10, 9
// > new fixed: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Hay que tener en cuenta que para poder usar el método sortInPlace la variable con la que hemos declarado el array debe ser eso, variable (var) ya que si la declaramos como constante (let) el compilador nos avisará de nuestra intención de modificar un elemento definido como inmutable.

Ambas funciones cuentan con una versión que admite como parámetro un closure en el que podemos definir la regla por la que se ordenarán los elementos.

Vamos a ver un ejemplo en el que establecemos que para un array de enteros (Int) el orden será: Primero los números impares y luego los números pares, ordenados de menor a mayor.

var mutable_array: [Int] =  [ 2, 8, 10, 3, 6, 5, 4, 7, 1, 9]

mutable_array.sortInPlace() 
{ 
    let pares: (lhs: Bool, rhs: Bool) = (lhs: ($0 % 2 == 0), rhs: ($1 % 2 == 0))

    switch pares
    {
        case (true, false):
            return false
        case (false, true):
            return true
        default:
            return $0 < $1
    }
}

print(mutable_array.descriptionWithSeparator(", "))

// En la consola de depuración se verá...
// 1, 3, 5, 7, 9, 2, 4, 6, 8, 10

Para la salida por la consola de depuración hemos añadido un método a todas las clases que cumplan con el protocolo CollectionType que lo único que hace es construir una cadena de texto con todos los elementos de la colección separador por un carácter o cadena de texto, aquí lo que cada uno prefiera 😉

extension CollectionType
{
    /**
        Construye una cadena de texto con los elementos contenidos

        - parameter separator: Un caracter que se emplea para separar los elementos
    */
    func descriptionWithSeparator(separator: String) -> String
    {
        return self.reduce(String()) 
        { 
            if String($0).isEmpty
            {
                return String($1)
            }
            else
            {
                return "\(String($0))\(separator)\(String($1))"
            } 
        }
    }
}

Antes de usar esta extensión te aviso que existen las variables description y debugDescription definidas en los protocolos CustomStringConvertible y CustomDebugStringConvertible respectivamente que listan el contenido de una colección.

Publicado en Swift

Comentarios

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *