检查可选数组是否为空

在 Objective-C 中,当我有一个数组时

NSArray *array;

我想检查它是否是空的,我总是这样做:

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

这样,就不需要检查 array == nil,因为这种情况会导致代码落入 else的情况,也可以使用非 nil但是空数组。

然而,在 Swift 中,我偶然发现了一种情况,即我有一个可选的数组:

var array: [Int]?

我不知道该使用哪个条件,我有一些选择,比如:

选项 A: 检查同一情况下的非 nil及空箱:

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

选项 B: 使用 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...")
}

选项 C: 使用 Swift 提供的结合运算符:

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

我不太喜欢 B选项,因为我在两种情况下重复代码。但是我真的不确定选项 AC是否正确,或者我应该使用任何其他方法来做到这一点。

我知道根据具体情况可以避免使用可选数组,但是在某些情况下,可能需要询问它是否为空。所以我想知道最简单的方法是什么。


编辑:

正如@vacawama 所指出的,这种简单的检查方法是有效的:

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

但是,我尝试了这样一种情况,即只有在 nil或为空时才执行特殊操作,然后不管数组是否有元素都继续执行。所以我试着:

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


// Do something regardless whether the array has elements or not.

还有

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


// Do something regardless whether the array has elements or not.

但是,当数组为 nil时,它不会落入 if体中。这是因为,在这种情况下,array?.count == nilarray?.isEmpty == nil,所以表达式 array?.count == 0array?.isEmpty == true都计算为 false

因此,我试图找出是否有任何方法来实现这一点,只有一个条件。

78340 次浏览

Swift 3及以上版本的最新答案:

Swift 3已经取消了将选项与 ><进行比较的能力,因此以前的答案的某些部分不再有效。

仍然可以将可选项与 ==进行比较,因此检查可选数组是否包含值的最直接方法是:

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

其他方法:

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!")
}

如果您想在数组为 nil或为空时执行某些操作,那么您至少有6种选择:

选择 A:

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

选择 B:

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

选择 C:

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

选择 D:

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

选项 E:

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

方案 F:

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

选项 C 准确地捕获了您用英语描述它的方式: “我想做一些特别的事情,只有当它是空的或空的时候。”我建议您使用这个选项,因为它很容易理解。这没有什么错,特别是因为它将“短路”,并跳过检查为空,如果变量是 nil



以前对 Swift 2.x 的回答:

你可以简单地做:

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

正如@Martin 在注释中指出的,它使用 func ><T : _Comparable>(lhs: T?, rhs: T?) -> Bool,这意味着编译器将 0包装为 Int?,这样就可以与左边的 Int?进行比较,因为可选的链接调用。

同样,你也可以这样做:

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

注意: 您必须显式地与 false进行比较才能使其正常工作。


如果您想在数组为 nil或为空时执行某些操作,那么您至少有7种选择:

选择 A:

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

选择 B:

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

选择 C:

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

选择 D:

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

选项 E:

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

方案 F:

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

方案 G:

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

选项 D 准确地捕获了您用英语描述它的方式: “我想做一些特别的事情,只有当它是空的或空的时候。”我建议您使用这个选项,因为它很容易理解。这没有什么错,特别是因为它将“短路”,并跳过检查为空,如果变量是 nil

条件拆封:

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

编辑: 可能性来自 Swift 1.2:

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

编辑: 可能是因为 Swift 2.0:

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

选项 D: 如果数组不需要是可选的,因为你只关心它是否为空,那么将它初始化为一个空数组,而不是可选的:

var array = [Int]()

现在它将始终存在,您可以简单地检查 isEmpty

Collection协议的扩展属性

* 用 Swift 3写的

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

示例使用:

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

其他选择

除了上面的扩展之外,我发现下面的选项非常清楚,没有强制展开选项。我将此解读为取消可选数组的包装,如果为 nil,则替换为相同类型的空数组。然后,获取它的(非可选)结果,如果它是 isEmpty,则执行条件代码。

推荐

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

尽管以下内容读起来很清楚,但我建议尽可能避免强制展开选项。虽然可以保证在这种情况下执行 array!.isEmpty时,array永远不会是 nil,但是以后编辑它会很容易,并且会在不经意间引起崩溃。当您适应强制展开选项时,您增加了某人在将来进行更改的机会,这些更改在运行时编译但崩溃。

不推荐!

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

我发现包含 array?(可选链接)的选项令人困惑,例如:

困惑?

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


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

快速扩展:

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
}
}

用法:

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

或:

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

优雅的内置解决方案是可选的 map方法。这个方法经常被遗忘,但是它确实满足了您的需要; 它允许您将消息发送到包装在可选项中的内容,这是安全的。在这种情况下,我们最终得到一种三路开关: 我们可以对可选数组说 isEmpty,然后得到 true、 false 或 nil (如果数组本身为 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)

与使用 ifelse不同,使用 guard检查空数组而不为同一数组创建新变量是更好的方法。

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

最好使用 if 检查空数组。为什么,例如,如果我们试图在一个列表数组中找到最大的整数,显然我们会比较列表[0]和列表中的每个整数。当时它给我们指数超出范围例外... 。你可以试试这两个 IF 和警卫

func findGreatestInList(list: [Int]?)-> Int? {
if list!.count == 0 {
print("List is empty")
return nil
           

}
/*guard list!.isEmpty else {
print("List is empty")
return nil
}*/
var greatestValue = list![0]
for number in 0...list!.count-1 {
            

if list![number] > greatestValue {
greatestValue = list![number]