如何判断变量是否为数组

时间:2014-10-07 00:40:29

标签: arrays swift

我有一个接受Any的Swift函数,我希望它能够接受一个字符串数组,一个Ints数组,一个混合数组或一个数组数组等。它也可以只接受一个字符串或者Int等,不在数组中。

所以我有这个:

    private func parse(parameter: Any) {
        if parameter is Int {
            // Int
        } else if (parameter is Float) || (parameter is Double) {
            // Double
        } else if parameter is String {
            // String
        } else if parameter is Bool {
            // Bool
        } else if let array = parameter as? [Any] {
            // Should catch all Arrays
        } else {
            assert(false, "Unsupported type") // [String] ends up here
        }
    }

但如果我调用parse(["Strings"]),则会引发断言。我怎样才能捕获所有类型的数组?

编辑 - 对于我想要完成的事情存在一些困惑。我基本上需要根据类型返回一个String,所以Int - > ""和字符串 - > "",所以数组会进行递归调用以返回" ..."

这篇文章被标记为重复,但另一个问题是关于Javascript,而不是Swift。

4 个答案:

答案 0 :(得分:10)

我终于找到了这样做的方法,即使用NSArray进行投射。

private func parse(x: Any) {
    if let o = x as? [Any] {
        println("[Any]")
    }
    if let o = x as? [AnyObject] {
        println("[AnyObject]")
    }
    if let o = x as? NSArray {
        println("NSArray")
    }
}

let a: [Any] = ["bar"]
let b: [AnyObject] = ["bar"]
let c = ["foo", 3.14]

parse(a) // ==> [Any]
parse(b) // ==> [AnyObject], and also NSArray
parse(c) // ==> NSArray

它看起来是一个包含Any内部NSArray值的数组。 (但它应该能够c投射到[Any] ......?我怀疑这是一个错误。)

答案 1 :(得分:2)

你可以做到这一点的一种方法是将函数分离出两个独立的实现(具有相同的名称),一个用于Array,另一个用于其他一切。您还需要将它们设为通用函数,而不是使用Any类型。通过该设置,Swift可以使用类型推断来找出要调用的最佳函数。

我实现了这样的事情(我只是println类型来显示事情的结局:

func parse<T>(parameter: T) {
    if parameter is Int {
        println("Int")
    } else if (parameter is Float) || (parameter is Double) {
        println("Double")
    } else if parameter is String {
        println("String")
    } else if parameter is Bool {
        println("Bool")
    } else {
        assert(false, "Unsupported type")
    }
}

func parse<T>(parameter: Array<T>) {
    println("Array")
    for element in parameter {
        // Recursively parsing...
        parse(element)
    }
}

然后这样称呼它:

parse(1)  // Int
parse(0.1) // Double
parse("asdf") // String
parse(true) // Bool
parse(["asdf", "asdf"]) // Array -> String String

输出:

Int
Double
String
Bool
Array
String
String

答案 2 :(得分:2)

理解Swift中键入和类型相关问题的关键是所有道路都会导致协议。

此问题的挑战是检测任何类型的数组,而不仅仅是一种具体类型。 OP的示例失败了,因为[Any]不是基类或[String]的通用模式,也就是说,(在我所知的情况下),在Swift [T] is not covariant on T中。除此之外,您无法检查SequenceType或CollectionType,因为它们具有关联类型(Generator.Element)。

因此,惯用解决方案是使用标记协议来指示您希望与您的条件匹配的类型。如下图所示,您可以通过创建一个空协议并将其与感兴趣的类型相关联来实现此目的。

import Foundation


protocol NestedType {}
extension Array: NestedType {}
extension Set: NestedType {}
extension Dictionary: NestedType {}
extension NSSet: NestedType {}

protocol AnyTypeOfArray {}
extension Array: AnyTypeOfArray {}
extension NSArray: AnyTypeOfArray {}

protocol AnyTypeOfDictionary {}
extension Dictionary: AnyTypeOfDictionary {}


func printType(v:Any) {
    if v is NestedType {
        print("Detected a nested type")
    }

    if v is AnyTypeOfArray {
        print("\t which is an array")
    }

    else if v is AnyTypeOfDictionary {
        print("\t which is a dictionary")
    }
}


printType([String:Int]())
printType([Int]())
printType(NSArray())

其输出为:

Detected a nested type
     which is a dictionary
Detected a nested type
     which is an array
Detected a nested type
     which is an array

答案 3 :(得分:0)

您可以使用_stdlib_getTypeName返回给定值的损坏类型名称。

例如:

    var myString = "String"
    var myInteger = 10
    var myArray = [10,22]
    var myDictionary = ["one": 1, "two": 2, "three": 3]
    println("\(_stdlib_getTypeName(myString))")
    println("\(_stdlib_getTypeName(myInteger))")
    println("\(_stdlib_getTypeName(myArray))")
    println("\(_stdlib_getTypeName(myDictionary))")

结果将是:

_TtSS // for String
_TtSi // for integer
_TtSa // for array
_TtVSs10Dictionary // for dictionary
相关问题