Compruebe si la matriz opcional está vacía

En Objective-C, cuando tengo una matriz

NSArray *array; 

y quiero verificar si no está vacío, siempre lo hago:

 if (array.count > 0) { NSLog(@"There are objects!"); } else { NSLog(@"There are no objects..."); } 

De esta forma, no es necesario verificar si array == nil ya que esta situación llevará al código a caer en el caso else , así como a una matriz no nil pero vacía.

Sin embargo, en Swift, me he topado con la situación en la que tengo una matriz opcional:

 var array: [Int]? 

y no puedo descifrar qué condición usar. Tengo algunas opciones, como:

Opción A: verifique los casos vacíos y no vacíos en la misma condición:

 if array != nil && array!.count > 0 { println("There are objects") } else { println("No objects") } 

Opción B: Desvincular la matriz con let :

 if let unbindArray = array { if (unbindArray.count > 0) { println("There are objects!") } else { println("There are no objects...") } } else { println("There are no objects...") } 

Opción C: uso del operador coalescente que proporciona Swift:

 if (array?.count ?? 0) > 0 { println("There are objects") } else { println("No objects") } 

No me gusta mucho la opción B porque estoy repitiendo el código en dos condiciones. Pero no estoy seguro de si las opciones A y C son correctas o debería usar cualquier otra forma de hacerlo.

Sé que el uso de una matriz opcional podría evitarse dependiendo de la situación, pero en algunos casos podría ser necesario preguntar si está vacío. Entonces me gustaría saber cuál es la manera de hacerlo de la manera más simple.


EDITAR:

Como señaló @vacawama, esta forma simple de verificarlo funciona:

 if array?.count > 0 { println("There are objects") } else { println("No objects") } 

Sin embargo, estaba probando el caso en el que quiero hacer algo especial solo cuando es nil o está vacío, y luego continúo independientemente de si la matriz tiene elementos o no. Así que lo intenté:

 if array?.count == 0 { println("There are no objects") } // Do something regardless whether the array has elements or not. 

Y también

 if array?.isEmpty == true { println("There are no objects") } // Do something regardless whether the array has elements or not. 

Pero, cuando la matriz es nil , no cae en el cuerpo if . Y esto se debe a que, en ese caso, array?.count == nil y array?.isEmpty == nil , por lo que las expresiones array?.count == 0 y array?.isEmpty == true evalúan como false .

Así que estoy tratando de averiguar si hay alguna forma de lograr esto con solo una condición también.

Respuesta actualizada para Swift 3:

Swift 3 ha eliminado la posibilidad de comparar opcionales con > y < , por lo que algunas partes de la respuesta anterior ya no son válidas.

Todavía es posible comparar los opcionales con == , por lo que la forma más sencilla de verificar si un conjunto opcional contiene valores es:

 if array?.isEmpty == false { print("There are objects!") } 

Otras formas en que se puede hacer:

 if array?.count ?? 0 > 0 { print("There are objects!") } if !(array?.isEmpty ?? true) { print("There are objects!") } if array != nil && !array!.isEmpty { print("There are objects!") } if array != nil && array!.count > 0 { print("There are objects!") } if !(array ?? []).isEmpty { print("There are objects!") } if (array ?? []).count > 0 { print("There are objects!") } if let array = array, array.count > 0 { print("There are objects!") } if let array = array, !array.isEmpty { print("There are objects!") } 

Si desea hacer algo cuando la matriz es nil o está vacía, tiene al menos 6 opciones:

Opción A:

 if !(array?.isEmpty == false) { print("There are no objects") } 

Opción B:

 if array == nil || array!.count == 0 { print("There are no objects") } 

Opción C:

 if array == nil || array!.isEmpty { print("There are no objects") } 

Opción D:

 if (array ?? []).isEmpty { print("There are no objects") } 

Opción E:

 if array?.isEmpty ?? true { print("There are no objects") } 

Opción F:

 if (array?.count ?? 0) == 0 { print("There are no objects") } 

La opción C captura exactamente cómo lo describió en inglés: "Quiero hacer algo especial solo cuando es nulo o está vacío". Le recomendaría que use esto ya que es fácil de entender. No hay nada de malo en esto, especialmente dado que se "cortocircuitará" y se saltará el cheque por vacío si la variable es nil .



Respuesta anterior para Swift 2.x:

Simplemente puede hacer:

 if array?.count > 0 { print("There are objects") } else { print("No objects") } 

Como señala @Martin en los comentarios, usa func >(lhs: T?, rhs: T?) -> Bool que significa que el comstackdor ajusta 0 como Int? para que la comparación se pueda hacer con el lado izquierdo que es un Int? debido a la llamada de encadenamiento opcional.

De manera similar, podrías hacer:

 if array?.isEmpty == false { print("There are objects") } else { print("No objects") } 

Nota: Aquí tiene que comparar explícitamente con false para que esto funcione.


Si desea hacer algo cuando la matriz es nil o está vacía, tiene al menos 7 opciones:

Opción A:

 if !(array?.count > 0) { print("There are no objects") } 

Opción B:

 if !(array?.isEmpty == false) { print("There are no objects") } 

Opción C:

 if array == nil || array!.count == 0 { print("There are no objects") } 

Opción D:

 if array == nil || array!.isEmpty { print("There are no objects") } 

Opción E:

 if (array ?? []).isEmpty { print("There are no objects") } 

Opción F:

 if array?.isEmpty ?? true { print("There are no objects") } 

Opción G:

 if (array?.count ?? 0) == 0 { print("There are no objects") } 

La opción D captura exactamente cómo lo describió en inglés: "Quiero hacer algo especial solo cuando es nulo o está vacío". Le recomendaría que use esto ya que es fácil de entender. No hay nada de malo en esto, especialmente dado que se "cortocircuitará" y se saltará el cheque por vacío si la variable es nil .

Opción D: si la matriz no necesita ser opcional, porque solo le importa si está vacía o no, inicialícela como una matriz vacía en lugar de una opción:

 var array = [Int]() 

Ahora siempre existirá, y simplemente puede verificar si está isEmpty .

Propiedad de extensión en el protocolo de recostackción

* Escrito en Swift 3

 extension Optional where Wrapped: Collection { var isNilOrEmpty: Bool { switch self { case .some(let collection): return collection.isEmpty case .none: return true } } } 

Ejemplo de uso:

 if array.isNilOrEmpty { print("The array is nil or empty") } 

Otras opciones

Además de la extensión anterior, considero que la siguiente opción es más clara sin necesidad de forzar los opcionales. Leo esto como desenvolver la matriz opcional y si es nula, sustituir una matriz vacía del mismo tipo. Luego, tomando el resultado (no opcional) de eso y si es isEmpty ejecuta el código condicional.

Recomendado

 if (array ?? []).isEmpty { print("The array is nil or empty") } 

Aunque lo siguiente se puede leer con claridad, sugiero el hábito de evitar la fuerza desenvolver los elementos opcionales siempre que sea posible. Aunque está garantizado que la array nunca será nil cuando la array!.isEmpty se ejecute en este caso específico, sería fácil editarla más tarde e inadvertidamente introducir una falla. Cuando te sientes cómodo al desempaquetar opcionales, aumentas las posibilidades de que alguien haga un cambio en el futuro que se comstack pero se bloquea en el tiempo de ejecución.

¡No recomendado!

 if array == nil || array!.isEmpty { print("The array is nil or empty") } 

Encuentro opciones que incluyen array? (encadenamiento opcional) confuso como:

¿Confuso?

 if !(array?.isEmpty == false) { print("The array is nil or empty") } if array?.isEmpty ?? true { print("There are no objects") } 

Desenvolvimiento condicional:

 if let anArray = array { if !anArray.isEmpty { //do something } } 

EDITAR: Posible desde Swift 1.2:

 if let myArray = array where !myArray.isEmpty { // do something with non empty 'myArray' } 

EDITAR: Posible desde Swift 2.0:

 guard let myArray = array where !myArray.isEmpty else { return } // do something with non empty 'myArray' 

Swift 3-4 compatible:

 extension Optional where Wrapped: Collection { var nilIfEmpty: Optional { switch self { case .some(let collection): return collection.isEmpty ? nil : collection default: return nil } } var isNilOrEmpty: Bool { switch self { case .some(let collection): return collection.isEmpty case .none: return true } } 

Uso:

 guard let array = myObject?.array.nilIfEmpty else { return } 

O

 if myObject.array.isNilOrEmpty { // Do stuff here } 

La elegante solución integrada es el método de map de Optional. Este método a menudo se olvida, pero hace exactamente lo que necesita aquí; te permite enviar un mensaje a la cosa envuelta dentro de un Opcional, de forma segura. En este caso, terminamos con una especie de interruptor de tres vías: podemos decir que es isEmpty para la matriz Opcional, y obtener verdadero, falso o nulo (en caso de que la matriz sea en sí misma nula).

 var array : [Int]? array.map {$0.isEmpty} // nil (because `array` is nil) array = [] array.map {$0.isEmpty} // true (wrapped in an Optional) array?.append(1) array.map {$0.isEmpty} // false (wrapped in an Optional)