swift - 将数组数据追加到Struct变量中

标签 swift

我想把数组的数据合并到我的结构变量中
下面是代码
我想在rest->distance中添加距离数组值

distance = ["12.44","45.32","56.1","54.22"]

将此距离数组合并为结构变量距离
var rest : [Restaurants] = []
var distance : [String] = []

struct Restaurants {
    var name:String
    var lat:Double
    var long:Double
    var distance:String?
}

let rest1 = Restaurants(name: "English Tea House", lat: 31.461812, long: 74.272524, distance: nil)
let rest2 = Restaurants(name: "Cafe Barbera", lat: 31.474536, long: 74.268103, distance: nil)
let rest3 = Restaurants(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908, distance: nil)
let rest4 = Restaurants(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124, distance: nil)
let rest5 = Restaurants(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603, distance: nil)
let rest6 = Restaurants(name: "Big Moes", lat: 31.467305, long: 74.256908, distance: nil)

rest.append(rest1)
rest.append(rest2)
rest.append(rest3)
rest.append(rest4)
rest.append(rest5)
rest.append(rest6)

for location in rest {
    distance.append(findDistance(from: location.lat, long: location.long))
}

// I want to add distance array values in rest -> distance 
func findDistance(from lat: Double, long: Double) -> Double {
    let source = CLLocation(latitude: 31.461512, longitude: 74.272024)
    let destination = CLLocation(latitude: lat, longitude: long)
    let distanceInMeters = source.distance(from: destination)
    return distanceInMeters
}

最佳答案

这里有很多事情要做,所以我会告诉你解决方法。
首先,rest是一个糟糕的变量名。当我第一次读它的时候,我以为这是“剩下的”,就像其他的东西一样,我在寻找“主要”数据在哪里。击键不需要花费美元,您只需输入restaurants
其次,创建一个空数组,并手动将所有这些餐馆追加到该数组中。相反,您只需从数组文字创建一个数组,它直接包含所有餐馆。不需要分开
为了回答您的直接问题,您可以使用ziprestdistance一起迭代,但问题是rest1rest2。。。变数,注定要失败。当您复制/粘贴一堆行,而忘记更改其中一行,意外地写入rest.append(rest6); rest.append(rest6),忘记rest7时会发生什么?
第三,您的findDistance(from:long:)函数接受两个Doubles(纬度和经度),并使用它们构造一个CLLocation。但是,当您查看这个函数的使用位置时,您已经有了一个CLLocation,它被分解成两个Doubles,只需要findDistance(from:long:)立即将它们重新组合成一个CLLocation。相反,只要让findDistance直接接受CLLocation
第四,Restaurants数据类型是miss-named。不是很多餐馆。它是一家餐厅的模型。据此命名:Restaurant
应用这些改进(并且在路上固定一堆数据),我们得到:

struct Restaurant {
    var name: String
    var lat: Double
    var long: Double
    var distance: String?
}

let restaurants = [
    Restaurant(name: "English Tea House", lat: 31.461812, long: 74.272524, distance: nil),
    Restaurant(name: "Cafe Barbera", lat: 31.474536, long: 74.268103, distance: nil),
    Restaurant(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908, distance: nil,
    Restaurant(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124, distance: nil),
    Restaurant(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603, distance: nil),
    Restaurant(name: "Big Moes", lat: 31.467305, long: 74.256908, distance: nil),
]

var distances = [Double]()
for location in restaurants {
    distance.append(findDistance(to: location))
}

func findDistance(to destination: CLLocation) -> Double {
    let source = CLLocation(latitude: 31.461512, longitude: 74.272024)

    let distanceInMeters = source.distance(from: destination)
    return distanceInMeters
}

直接问题
在这里,我将演示我处理直接问题的过程。但是,不要使用这些。所有这些都是卑鄙的设计试图解决潜在的设计缺陷。我展示它们是为了演示连续的优化是什么样子。
现在,为了解决直接的问题:
首次尝试:使用zip(_:_:)
第一种解决方法可能是使用zip并行迭代restaurantsdistances,然后从每个距离对每个restaurant进行变异。像这样的:
for (restaurant, distance) in zip(restaurants, distances) {
   restaurant.distance = distance
}

不过,这是行不通的。因为Restaurant是一个值类型,所以循环中的restaurant变量是数组中变量的副本。设置其距离会使副本发生变化,但不会影响数组中的原始副本。
第二次尝试:人工索引
我们可以通过循环索引来解决这一问题,尽管方式不那么漂亮:
for i in restaurants.indices {
    restaurants[i] = distances[i]
}

第三次尝试:跳过distances数组。
第二次尝试是有效的,但是如果distances的唯一目的是用一堆值填充它,只是立即使用并丢弃它们,那么为什么我们都有数组呢?
for i in restaurants.indices {
    restaurant.location = findDistance(to: location)
}

不过,这仍然不太好。Restaurant数据类型经历两个阶段的初始化,即acode smell。首先我们用nil位置初始化它,然后将其设置为实际位置。为什么要麻烦?为什么我们不直接设定地点?
let distance = findDistance(to: location)
let restaurants = [
    Restaurant(name: "English Tea House", lat: 31.461812, long: 74.272524, distance: distance),
    Restaurant(name: "Cafe Barbera", lat: 31.474536, long: 74.268103, distance: distance),
    Restaurant(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908, distance: distance),
    Restaurant(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124, distance: distance),
    Restaurant(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603, distance: distance),
    Restaurant(name: "Big Moes", lat: 31.467305, long: 74.256908, distance: nil),
]

但这仍然不是好的设计。。。
findDistance(to:)Restaurant.distance修复缺陷
findDistance(to:)到底做了什么?在内部,它与一些硬编码、未命名的位置有一定的距离。当我说“抄送”时,我会期待与我保持距离。如果它距离某个引用点a有一定距离,那么我希望API的拼写应该类似于CLLocation(latitude: 31.461512, longitude: 74.272024),或者类似于这样。
此外,为什么存储与其他对象的距离是someRestaurant.distance的工作?如果我想要someResaurant.distanceFromNorthPoleRestaurant?API会变得非常臃肿,而restaurant.distanceToSouthPole类型最终会做得太多。如果我restaurant.distanceToEquator?我可以移动,当我移动时,一个预先计算的存储值如何跟上我?
解决办法是根本不存储距离。相反,提供一个API,该数据类型的用户可以使用它计算到自己选择的任何点的距离。

struct Restaurant {
    var name: String
    var lat: Double
    var long: Double

    func distance(from other: CLLocation) -> Double {
        let selfLocation = CLLocation(latitude: self.lat, longitude: self.long)
        return selfLocation.distance(from: other)
    }
}

let restaurants = [
    Restaurant(name: "English Tea House", lat: 31.461812, long: 74.272524),
    Restaurant(name: "Cafe Barbera", lat: 31.474536, long: 74.268103),
    Restaurant(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908),
    Restaurant(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124),
    Restaurant(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603),
    Restaurant(name: "Big Moes", lat: 31.467305, long: 74.256908),
]

let pointA = CLLocation(latitude: 31.461512, longitude: 74.272024) // Name me!

// and now, whenever you need the distance to pointA:

for restaurant in restaurants {
    let distanceFromA = restaurant.distance(from: pointA)
    // This is for the purpose of a simple example only. Never hard code units like this,
    // Use `Measurement` and `MeasurementFormatter` to create textual representations
    // of measurements in the correct units, language and format for the user's locale.
    print("\(restaurant.name) is \(distanceFromA) meters from \(pointA)")

}

令人惊讶的是,这仍然不是我们能做到的最好的!
不要把双打储存起来
这就是restaurant的作用。注意,几乎所有使用restaurant.distanceToMeCLLocation的都需要先将其装箱到lat。所以让我们直接存储它,而不是分离单个组件并独立地传递它们。这可以防止像long这样的错误。
struct Restaurant {
    var name: String
    var location: CLLocation

    func distance(from other: CLLocation) -> Double {
        return self.location.distance(from: other)
    }
}

但是,如果您这样做,初始化器现在需要一个CLLocation而不是两个单独的useLocation(lat: self.lat, long: self.long /* oops! */)/CLLocationlats。这对于与位置api交互(其中long是用于交换位置信息的“通用货币”类型)更好,但对于硬编码的位置(如您的餐厅)则更麻烦,因为你所有的初始化器调用都会被一堆对Double的调用所膨胀:
let restaurants = [
    Restaurant(name: "English Tea House", CLLocation(latitude: 31.461812, longitude: 74.272524)),
    Restaurant(name: "Cafe Barbera", CLLocation(latitude: 31.474536, longitude: 74.268103)),
    Restaurant(name: "Butler's Chocolate", CLLocation(latitude: 31.467505), longitude: 74.251908)),
    Restaurant(name: "Freddy's Cafe", CLLocation(latitude: 31.461312, longitude: 74.272124)),
    Restaurant(name: "Arcadian Cafe", CLLocation(latitude: 31.464536, longitude: 74.268603)),
    Restaurant(name: "Big Moes", CLLocation(latitude: 31.467305, longitude: 74.256908)),
]

为了解决这个问题,我们可以将CLLocation塞进一个小的初始化器中,以方便使用。我是在CLLocation.init(latitude:longitude:)的扩展中这样做的,而不是直接在CLLocation.init(latitude:longitude:)的初始声明中这样做,因为这样做会保留编译器生成的初始值设定项(称为“成员级初始值设定项”),否则将被替换:
extension Restaurant {
    init(name: String, lat: Double, long: Double) {
        self.init(name: name, location: CLLocation(latitude: lat, long))
    }
}

这使我们可以重新获得以前的好语法:
let restaurants = [
    Restaurant(name: "English Tea House", lat: 31.461812, long: 74.272524),
    Restaurant(name: "Cafe Barbera", lat: 31.474536, long: 74.268103),
    Restaurant(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908),
    Restaurant(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124),
    Restaurant(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603),
    Restaurant(name: "Big Moes", lat: 31.467305, long: 74.256908),
]

易变性
在你的应用程序的一个实例的生命周期内,餐厅名称和位置不太可能改变,因此不需要保持它们的可变。所以让我们修正一下:
struct Restaurant {
    var name: String
    var location: CLLocation

    func distance(from other: CLLocation) -> Double {
        return self.location.distance(from: other)
    }
}

最后。。。
我们已经到了最后阶段。一个名为Restaurant的程序,它不需要两阶段初始化,为用户可能喜欢的任何点提供最新的距离数据,并且由于RestaurantRestaurant被粘在一起而不易出现复制粘贴错误。
struct Restaurant {
    var name: String
    var location: CLLocation

    func distance(from other: CLLocation) -> Double {
        return self.location.distance(from: other)
    }
}

extension Restaurant {
    init(name: String, lat: Double, long: Double) {
        self.init(name: name, location: CLLocation(latitude: lat, long))
    }
}

let restaurants = [
    Restaurant(name: "English Tea House", lat: 31.461812, long: 74.272524),
    Restaurant(name: "Cafe Barbera", lat: 31.474536, long: 74.268103),
    Restaurant(name: "Butler's Chocolate", lat: 31.467505, long: 74.251908,
    Restaurant(name: "Freddy's Cafe", lat: 31.461312, long: 74.272124),
    Restaurant(name: "Arcadian Cafe", lat: 31.464536, long: 74.268603),
    Restaurant(name: "Big Moes", lat: 31.467305, long: 74.256908),
]

let pointA = CLLocation(latitude: 31.461512, longitude: 74.272024) // Name me!

// and now, whenever you need the distance to pointA you can do this (for example):

for restaurant in restaurants {
    let distanceFromA = restaurant.distance(from: pointA)
    // This is for the purpose of a simple example only. Never hard code units like this,
    // Use `Measurement` and `MeasurementFormatter` to create textual representations
    // of measurements in the correct units, language and format for the user's locale.
    print("\(restaurant.name) is \(distanceFromA) meters from \(pointA)")

}

关于swift - 将数组数据追加到Struct变量中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55893353/

相关文章:

ios - 检索我们处于生命周期 Controller 的哪个状态

swift - 是否可以像 C# 一样检查 Swift 中的类型?

带有 AnyView 的 SwiftUI 对象数组

ios - 快速锁定 viewController 的方向

json - 如何在 Swift 中解码具有许多唯一键的嵌套 JSON?

ios - 如何获取总已使用内存

swift - 如何在 Swift 中将两个自定义单元格添加到 Storyboard的 tableview 中?

swift - 在 swift 中内联 if 条件为 nil

ios - 使用 Core Data(在 SwiftUI 中)提供的数据并与另一个 View 共享

python - CoreML - 多数组输入需要在应用程序或模型中进行预处理?