如何初始化信息数组并附加

时间:2017-01-07 16:45:46

标签: arrays swift dictionary

我希望能够初始化一个能够[7]能够保存类似于以下信息的空数组结构:

.append()

这是一个字典数组数组的数据类型吗?我希望能够通过var locations = [ ["title": "New York, NY", "latitude": 40.713054, "longitude": -74.007228], ["title": "Los Angeles, CA", "latitude": 34.052238, "longitude": -118.243344], ["title": "Chicago, IL", "latitude": 41.883229, "longitude": -87.632398] ] 访问titlelatitudelongitude并且我从未使用过类似的内容,因此我不确定如何初始化和location

5 个答案:

答案 0 :(得分:1)

是的,它是一个字典数组,但字典值是StringDouble类型,因此为了适应这两个值,字典类型将是{{1 }}

如果您明确地为location变量的类型转换(而不是推断),那么它将是:

<String: Any>

要访问数组中的值,您可以使用索引下标,其中为该位置的字典索引传入var locations: [Dictionary<String, Any>] = ...

Int

您可以深入挖掘第二个下标,访问字典键的值:

let firstLocation = locations[0]
// firstLocation: [String: Any]
// firstLocation -> [ "title": "New York, NY", "latitude": 40.713054, "longitude": -74.007228]

要访问基础字符串类型,您需要从let firstLocationTitle = locations[0]["title"] // firstLocationTitle: Any? // firstLocationTitle -> New York, NY let message = "I'm in" + firstLocationTitle // fails because operator '+' cannot be applied to operands of type 'String' and 'Any?' 投射到Any?

String

要附加新位置,只需要使用相同的类型,此处就可以将波士顿词典添加到位置:

let firstLocationTitle = locations[0]["title"] as! String
// firstLocationTitle: String
// firstLocationTitle -> New York, NY

let message = "I'm in" + firstLocationTitle
// message -> "I'm in New York, NY"

答案 1 :(得分:1)

您的结构是一系列词典:[[String : Any]]

正如@Hamish在评论中建议的那样,您可以更好地将数据存储为一系列结构。

以下是一种可能的实施方式:

struct Location: CustomStringConvertible {
    var title: String
    var latitude: Double
    var longitude: Double

    var description: String { return "(title: \(title), latitude: \(latitude), longitude: \(longitude))"}
}

var locations = [
    Location(title: "New York, NY", latitude: 40.713054, longitude: -74.007228),
    Location(title: "Los Angeles, CA", latitude: 34.052238, longitude: -118.243344),
    Location(title: "Chicago, IL", latitude: 41.883229, longitude: -87.632398)
]

// Append a new location...    
locations.append(Location(title: "Boston, MA", latitude: 42.3601, longitude: -71.0589))

print(locations)
[(title: New York, NY, latitude: 40.713054, longitude: -74.007228),
(title: Los Angeles, CA, latitude: 34.052238, longitude: -118.243344),
(title: Chicago, IL, latitude: 41.883229, longitude: -87.632398),
(title: Boston, MA, latitude: 42.3601, longitude: -71.0589)]
func lookUp(title: String, in locations: [Location]) -> [Location] {
    return locations.filter { $0.title.range(of: title) != nil }
}

print(lookUp(title: "CA", in: locations))
[(title: Los Angeles, CA, latitude: 34.052238, longitude: -118.243344)]
print(lookUp(title: "Chicago", in: locations))
[(title: Chicago, IL, latitude: 41.883229, longitude: -87.632398)]

答案 2 :(得分:1)

以下是@vacawama答案的Dictionary版本。它可以更好地(或更糟)适合某些用例。

此版本有一些值得注意的改进:

  1. 在字典中查找密钥非常快O(1),因为当列表增长到数百个城市O(N)时,在数组上使用find()执行得非常差。
  2. 字符串在堆上分配。这意味着设计的坐标struct在性能方面的行为类似于class(较慢)。您的问题并未在struct
  3. 中存储位置名称

    首先创建一个表示坐标的结构。

    struct Coordinate {
        /// Latitude in decimal notation
        let latitude: Double
    
        /// Longitude in decimal notation
        let longitude: Double
    }
    

    然后创建空集合(根据您的问题)

    /// Empty mapping of location string to latitude-longitude
    var coordinates = [String: Coordinate]()
    

    以下是填充字典的一种方法示例

    /// Populate the locations
    coordinates["New York, NY"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    coordinates["Los Angeles, CA"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    coordinates["Chicago, IL"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    

    示例输出:

    print(coordinates["New York, NY"] ?? "Unknown Location”)
    > "Coordinates(latitude: 40.713054, longitude: -74.007227999999998)”
    

    就是这样!

    再远一点......

    如果事先已知位置,并且如果没有数百个位置,您可以尝试使用字符串支持的enum

    上面应该回答原始问题,但是Swift允许使用类型系统更有趣的方法。

    我们保证Coordinate是一对Double个数字,真棒​​!但是,无法保证位置的完整性。稍后您可能会意外键入coordinates[“New york, NY”]。这将失败,因为“约克”是小写的! (以及目前发布的其他答案)。这是枚举:

    enum Location: String {
        case NY_NewYork = "New York, NY"
        case CA_LosAngeles = "Los Angeles, CA"
        case IL_Chicago = "Chicago, IL"
    }
    

    并相应地更改字典键和用法

    /// Empty mapping of location string to latitude-longitude
    var coordinates = [Location: Coordinate]()
    
    /// Populate the locations
    coordinates[.NY_NewYork] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    coordinates[.CA_LosAngeles] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    coordinates[.IL_Chicago] = Coordinate(latitude: 40.713054, longitude: -74.007228)
    

    我们仍然拥有原始的“纽约,纽约”标题,但它静态地表示为值Location.NY_NewYork。这意味着编译器将捕获您可能犯的任何错误!

    还有一件事:现在该位置是一个静态常量值,我们实际上可以将它放回struct内而不会产生可怕的堆分配! (struct值将是对枚举值的引用。)

    这是最终版本:

    enum Location: String {
        case NY_NewYork = "New York, NY"
        case CA_LosAngeles = "Los Angeles, CA"
        case IL_Chicago = "Chicago, IL"
    }
    
    struct Coordinate {
        /// The logical name of the location referenced by this coordinate
        let location: Location
    
        /// Latitude in decimal notation
        let latitude: Double
    
        /// Longitude in decimal notation
        let longitude: Double
    }
    
    /// Empty mapping of location string to latitude-longitude
    var coordinates = [Location: Coordinate]()
    
    /// Populate the locations
    coordinates[.NY_NewYork] = Coordinate(location: .NY_NewYork, latitude: 40.713054, longitude: -74.007228)
    coordinates[.CA_LosAngeles] = Coordinate(location: .CA_LosAngeles, latitude: 40.713054, longitude: -74.007228)
    coordinates[.IL_Chicago] = Coordinate(location: .IL_Chicago, latitude: 40.713054, longitude: -74.007228)
    // or if initializing from a data source, something like...
    // if let loc = Location(rawValue: "Chicago, IL") {
    //     coordinates[loc] = Coordinate(location: loc, latitude: 40.713054, longitude: -74.007228)
    // }
    

    输出

    print(coordinates[Location.NY_NewYork] ?? "uknown”)
    > "Coordinate(location: Location.NY_NewYork, latitude: 40.713054, longitude: -74.007227999999998)”
    

    酷!现在我们拥有完美的类型安全性,保持位置标题的便利性以及非常高性能的架构。

    这使得Swift成为iOS的特殊工具。

答案 3 :(得分:0)

var locations = [
    ["title": "New York, NY",    "latitude": 40.713054, "longitude": -74.007228],
    ["title": "Los Angeles, CA", "latitude": 34.052238, "longitude": -118.243344],
    ["title": "Chicago, IL",     "latitude": 41.883229, "longitude": -87.632398]
]
for(loc) in locations {
    if let title = loc["title"] as? String, let lat = loc["latitude"] as? Double, let lon = loc["longitude"] as? Double {
        print("title: \(title), latitude:\(lat), longitude:\(lon)")
    }
}

答案 4 :(得分:0)

最好使用带有元组的 字典。这样你就可以确保你拥有独特的钥匙。

myCities["New York, NY"] = (40.713054,-74.007228)
myCoordinates = myCities["New York, NY"]?
print(String(describing: myCoordinates?.0))
print(String(describing: myCoordinates?.1))
myCoordinates = myCities["Los Angeles, CA"]
print(String(describing: myCoordinates?.0))
print(String(describing: myCoordinates?.1))

键(字符串类型)是城市名称,元组(两个浮点类型)是您的经度/纬度值。

Optional(40.7130547)
Optional(-74.007225)
nil
nil

此代码生成以下控制台输出:

{{1}}