En Objective-C, cuando tengo una matriz

NSArray *array;

y quiero ver si no está vacía, yo siempre hago:

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

De esa manera, no es necesario comprobar si array == nil ya que esta situación va a llevar el código a caer en la else caso, así como un no-nil pero matriz vacía haría.

Sin embargo, en Swift, he tropezado a través de la situación en la que tengo un array opcional:

var array: [Int]?

y no estoy siendo capaz de averiguar qué condición de uso. Tengo algunas opciones, como por ejemplo:

Opción a: Comprobar tanto nonil y vacío de los casos en la misma condición:

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

Opción B: Separar la matriz de uso de la 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: Mediante la creación de operador que Swift ofrece:

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

No me gusta la opción de B mucho, porque yo soy la repetición de código en dos condiciones. Pero no estoy muy segura acerca de si las opciones de Un y C son correctos o que debo utilizar de cualquier otro modo de hacer esto.

Sé que el uso de un array opcional podrían evitarse dependiendo de la situación, pero en algunos casos podría ser necesario preguntar si está vacía. Así que me gustaría saber cuál es el camino para hacer de la manera más sencilla.


EDICIÓN:

Como @vacawama señalado, esta simple manera de comprobar que funciona:

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

Sin embargo, yo estaba tratando el caso en el que quiero hacer algo especial, sólo cuando es nil o vacío, y luego continuar con independencia de si la matriz tiene elementos o no. Así que he intentado:

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 caer en la if cuerpo. Y esto es porque, en ese caso, array?.count == nil y array?.isEmpty == nil, por lo que las expresiones array?.count == 0 y array?.isEmpty == true evaluar a false.

Así que estoy tratando de averiguar si hay alguna manera de lograr esto con solo una condición así.

  • Hay una razón por la que hizo la matriz opcional? Para las vistas de tabla y cosas que yo uso no opcional, ya que (como se dijo) nil es el mismo que ninguno de los objetos y por la eliminación de la nada usted reducir la complejidad sin perder ninguna funcionalidad.
  • Creo que la opción A es la más legible. Esa es la única cosa que usted debe cuidar de la palestra.
InformationsquelleAutor eze.scaruli | 2014-12-21

7 Comentarios

  1. 123

    Respuesta actualizada para Swift 3 y por encima de:

    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 opcionales con ==, por lo que la forma más sencilla de comprobar si una matriz opcional contiene valores es:

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

    Otras maneras 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 quieres hacer algo cuando la matriz es nil o está vacío, tiene por lo 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")
    }

    Opción C captura exactamente cómo usted describió en inglés: «quiero hacer algo especial sólo cuando es nulo o vacío.» Le recomendamos que utilice, ya que es fácil de entender. No hay nada de malo con esto, especialmente desde que se «corto circuito» y omitir la comprobación de vacío si la variable es nil.



    Respuesta anterior para Swift 2.x:

    Usted puede simplemente hacer:

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

    Como @Martin señala en los comentarios, utiliza func ><T : _Comparable>(lhs: T?, rhs: T?) -> Bool lo que significa que el compilador envuelve 0 como un Int? por lo que la comparación puede ser realizada con la mano izquierda, que es un Int? debido a la opcionales encadenamiento de llamada.

    De una manera similar, se podría:

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

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


    Si quieres hacer algo cuando la matriz es nil o está vacío, tiene por lo 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")
    }

    Opción D captura exactamente cómo usted describió en inglés: «quiero hacer algo especial sólo cuando es nulo o vacío.» Le recomendamos que utilice, ya que es fácil de entender. No hay nada de malo con esto, especialmente desde que se «corto circuito» y omitir la comprobación de vacío si la variable es nil.

    • Esto funciona. Sólo para la integridad: Se utiliza el func ><T : _Comparable>(lhs: T?, rhs: T?) -> Bool operador, y en la parte derecha 0 está envuelta en una Int? por el compilador.
    • Me di cuenta de que con var opt : Int? = nil, opt < 0 evalúa a true. No es relevante aquí, pero puede ser inesperado, y puede ser argumento contra comparar opcional enteros.
    • nil es menos que cualquier no-nil valor Int que lanzar en él, incluso las negativas. Tiene que ser en un extremo o el otro de los envueltos de tipo debido a la aplicación de < tiene que ser un orden total, y opcionalmente, puede envolver cualquier otro tipo. Creo que nil menos de lo que algunos nada es intuitiva, ya que si alguien se ordenan en una columna de números que podrían estar en blanco, creo que sería de esperar, los espacios en blanco de venir antes de 1. O, alternativamente, una nulo de la matriz de variable es aún más vacío que un array vacío 🙂
    • Gracias, @vacawama. La opción que señaló obras. Sin embargo, me fui un poco más adelante y trató de otro caso particular: sólo comprueba si la matriz es nulo o vacío, independientemente de hacer cualquier cosa cuando tiene elementos. Voy a editar mi pregunta, así que usted puede tener una mirada en ella.
    • Podría usted por favor decirme por qué usa «!(matriz?.isEmpty == false)» como opuesto a «de la matriz?.isEmpty == true»
    • false) se true si array es nil, pero array?.isEmpty == true será false si array es nil porque nil no es igual a true. Queremos tratar un nil array como vacío.
    • gracias!
    • Aha! Primer tiempo, saber que Swift apoya ?? el operador! Increíble.

  2. 7

    Extensión de la Propiedad en el Collection Protocolo

    *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

    La extensión anterior, creo que la siguiente opción más clara sin la fuerza de desenrollado opcionales. He leído esta como a desenvolver la matriz opcional y si nil, la sustitución de una matriz vacía del mismo tipo. A continuación, tomar el (no opcional) resultado de y si isEmpty ejecutar el código condicional.

    Recomienda

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

    Aunque la siguiente lee claramente, me sugieren un hábito de evitar la fuerza de desenrollado opcionales siempre que sea posible. A pesar de que tienes la garantía de que array nunca será nil cuando array!.isEmpty se ejecuta en este caso específico, sería fácil de editar más tarde, y sin querer introducir un accidente. Cuando usted se convierte en cómodo fuerza de desenrollado opcionales, aumentar la posibilidad de que alguien va a hacer un cambio en el futuro que compila, pero se bloquea en tiempo de ejecución.

    No Se Recomienda!

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

    Me parece de opciones que incluyen array? (opcional encadenamiento) confuso, tales como:

    Confuso?

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

    Opción D: Si la matriz no tiene que ser opcional, ya que en realidad sólo importa si es vacío o no, llegará como un array vacío en lugar de un opcional:

    var array = [Int]()

    Ahora va a existir siempre, y usted puede comprobar simplemente para isEmpty.

    • Aunque estoy de acuerdo con esto, el problema es que no sabemos lo que el OP quiere exactamente. Dependiendo de la API que se utiliza es posible que una matriz tiene contenidos, o es nil. O es nula, vacía o contiene los valores. Y cada una de estas situaciones tiene diferentes soluciones.
    • De acuerdo, yo era sólo la presentación de una opción que he encontrado personalmente útil.
    • Lol, sí. Sólo me comentó que la cosa exacta antes de leer tu respuesta. Grandes mentes… 🙂
    • Las vistas de tabla es exactamente la situación que estoy pensando!
  4. 4

    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
    }
  5. 3

    Condicional desenvoltura:

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

    EDITAR: es Posible desde Swift 1.2:

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

    EDITAR: es Posible desde Swift 2.0:

    guard let myArray = array where !myArray.isEmpty else {
        return
    }
    // do something with non empty 'myArray'
    • Él todavía tiene que comprobar si está vacía o no. Esto sólo comprueba si no la opcional que contiene una matriz.
    • Sí, entonces usted puede hacer if array? != nil && !(array!.isEmpty) {}
    • Usted puede simplemente quitarle el envoltorio, porque la línea no se ejecuta si la matriz es nula y no puede ser envueltos
    • No creo tener que escribir array? y array! en la misma línea para ser un código olor? Eso es lo condicional de desenrollado es para.
    • Pero cuidado, usted tiene que utilizar la lógica y aplicaciones de los operadores;- > tienes que utilizar && en lugar de &. De lo contrario, usted podría obtener un error cuando la matriz es nula.
    • Usted podría también utilizar array?.isEmpty pero cuando el uso de la lógica & operador que no hay necesidad de hacerlo
    • En Swift 2.0 edición, usted debe poner más después de la isEmpty. @OliverBorchert

  6. 0

    La elegante solución integrada es Opcional la map método. Este método es a menudo olvidado, pero hace exactamente lo que usted necesita aquí; permite que usted envíe un mensaje a la cosa envuelta dentro de un Facultativo, de manera segura. Terminamos en este caso con una especie de trio conmutador: podemos decir isEmpty a la matriz Opcional, y obtener verdadero, falso o nulo (en el caso de que la matriz es de por sí nil).

    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)
  7. 0

    Lugar de utilizar if y else es mejor sólo para uso guard para comprobar la matriz vacía sin la creación de nuevas variables para la misma matriz.

    guard !array.isEmpty else {
        return
    }
    // do something with non empty ‘array’

Dejar respuesta

Please enter your comment!
Please enter your name here