在 Swift 4 中创建 class 的非零属性数组
Create array of non-nil properties of a class in Swift 4
我创建了一个包含所有可选属性的 class。我正在尝试创建一个 var
的计算 returns 对象的所有非零属性。
[<array of stuff>].flatMap{ [=19=] }
似乎是显而易见的选择,但当我在 Playground 中修改它时,它仍然是 returns 一个包含 nil
个值的数组。
以下是我尝试获取 class 的非零属性数组的各种迭代:
假设我这样声明我的对象:
let lastSearch = LastSearch(startDate: startDate, endDate: endDate, minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)
尝试 #1:
在我的 class 中,我正在尝试创建一个 nonNilProperties
计算变量:
var nonNilProperties: Any {
return [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth , maxDepth].flatMap{ [=13=] } as Any
}
这是我打印 lastSearch.nonNilProperties
:
时在控制台中打印的内容
[Optional(2015-10-01 13:23:32 +0000), Optional(2015-10-07 01:43:59 +0000), Optional(1.0), Optional(5.0), nil, nil, nil, nil, nil, nil]
尝试 #2:
如果我在每个 属性 之后添加 as Any
,它会平息编译器警告并且填充的值不会在它们前面打印 "Optional",但它仍然有 null
值:
var nonNilProperties: Any {
return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ [=15=] } as [AnyObject]
}
这是我打印时在控制台中打印的内容:
[2015-10-01 13:23:32 +0000, 2015-10-07 01:43:59 +0000, 1, 5, <null>, <null>, <null>, <null>, <null>, <null>]
感谢您的阅读。我欢迎你的建议。这是 class 的样子:
class LastSearch {
private var startDate: Date?
private var endDate: Date?
private var minMagnitude: Double?
private var maxMagnitude: Double?
private var minLongitude: Double?
private var maxLongitude: Double?
private var minLatitude: Double?
private var maxLatitude: Double?
private var minDepth: Double?
private var maxDepth: Double?
private var nonNilProperties: Any {
return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ [=17=] } as Any
}
init(startDate: Date?, endDate: Date?,
minMagnitude: Double?, maxMagnitude: Double?,
minLongitude: Double?, maxLongitude: Double?,
minLatitude: Double?, maxLatitude: Double?,
minDepth: Double?, maxDepth: Double?) {
// Dates
self.startDate = startDate
self.endDate = endDate
// Magnitude Values
self.minMagnitude = minMagnitude
self.maxMagnitude = maxMagnitude
// Geographic Coordinates
self.minLongitude = minLongitude
self.maxLongitude = maxLongitude
self.minLatitude = minLatitude
self.maxLatitude = maxLatitude
// Depth Values
self.minDepth = minDepth
self.maxDepth = maxDepth
}
}
一个解决方案是显式地创建一个类型为 [Any]
的新数组,并且仅在 属性 不是 nil
时才将其添加到数组中。
public var nonNilProperties: [Any] {
let allProperties: [Any?] = [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth]
var output = [Any]()
for property in allProperties {
if let nonNilProperty = property {
output.append(nonNilProperty)
}
}
return output
}
或者您可以使用更接近原始解决方案的 flatMap
(归功于@Leo Dabus)
public var nonNilProperties: [Any] {
return ([startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth] as [Any?]).flatMap { [=11=] }
}
测试用例:
let lastSearch = LastSearch(startDate: Date(), endDate: Date(), minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)
print(lastSearch.nonNilProperties)
输出:
[2017-11-26 02:00:13 +0000, 2017-11-26 02:00:13 +0000, 1.0, 5.0]
这可行,但有点笨拙。根据您的具体情况,可能有更好的方法来构建您的数据。
第一个 nonNilProperties 不是 Any,它是 [Any](任意数组)。而且您不需要将每个 属性 都转换为 any,它会自动执行。其次,flatMap 不是您所需要的。使用地图。 flatMap 不会遍历元素,而是对整个数组进行操作。以下是一些示例:http://sketchytech.blogspot.ru/2015/06/swift-what-do-map-and-flatmap-really-do.html
正如 Leo Dabus 在评论中指出的那样,如果我不知道它们是什么,那么单独拥有非 nil 值是没有用的。也就是说,这就是我最终所做的:
在答案中,我找到了一种解包可选值的方法。
我将此方法添加到我的 class:
func unwrap<T>(_ any: T) -> Any {
let mirror = Mirror(reflecting: any)
guard mirror.displayStyle == .optional, let first = mirror.children.first else {
return any
}
return unwrap(first.value)
}
然后,我创建了一个计算变量 return 一个 Dictionary
的非零值,使用 Mirror
.
获取键和值
var nonNilPropertyDict: [String: Any] {
let keys = Mirror(reflecting: self).children.flatMap { [=11=].label }
let values = Mirror(reflecting: self).children.flatMap { unwrap([=11=].value) as! AnyObject }
var dict = Dictionary(uniqueKeysWithValues: zip(keys, values))
var keysToRemove = dict.keys.filter{ dict[[=11=]] is NSNull }
for key in keysToRemove {
dict.removeValue(forKey: key)
}
return dict
}
我创建了一个包含所有可选属性的 class。我正在尝试创建一个 var
的计算 returns 对象的所有非零属性。
[<array of stuff>].flatMap{ [=19=] }
似乎是显而易见的选择,但当我在 Playground 中修改它时,它仍然是 returns 一个包含 nil
个值的数组。
以下是我尝试获取 class 的非零属性数组的各种迭代:
假设我这样声明我的对象:
let lastSearch = LastSearch(startDate: startDate, endDate: endDate, minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)
尝试 #1:
在我的 class 中,我正在尝试创建一个 nonNilProperties
计算变量:
var nonNilProperties: Any {
return [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth , maxDepth].flatMap{ [=13=] } as Any
}
这是我打印 lastSearch.nonNilProperties
:
[Optional(2015-10-01 13:23:32 +0000), Optional(2015-10-07 01:43:59 +0000), Optional(1.0), Optional(5.0), nil, nil, nil, nil, nil, nil]
尝试 #2:
如果我在每个 属性 之后添加 as Any
,它会平息编译器警告并且填充的值不会在它们前面打印 "Optional",但它仍然有 null
值:
var nonNilProperties: Any {
return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ [=15=] } as [AnyObject]
}
这是我打印时在控制台中打印的内容:
[2015-10-01 13:23:32 +0000, 2015-10-07 01:43:59 +0000, 1, 5, <null>, <null>, <null>, <null>, <null>, <null>]
感谢您的阅读。我欢迎你的建议。这是 class 的样子:
class LastSearch {
private var startDate: Date?
private var endDate: Date?
private var minMagnitude: Double?
private var maxMagnitude: Double?
private var minLongitude: Double?
private var maxLongitude: Double?
private var minLatitude: Double?
private var maxLatitude: Double?
private var minDepth: Double?
private var maxDepth: Double?
private var nonNilProperties: Any {
return [startDate as Any, endDate as Any, minMagnitude as Any, maxMagnitude as Any, minLongitude as Any, maxLongitude as Any, minLatitude as Any, maxLatitude as Any, minDepth as Any, maxDepth as Any].flatMap{ [=17=] } as Any
}
init(startDate: Date?, endDate: Date?,
minMagnitude: Double?, maxMagnitude: Double?,
minLongitude: Double?, maxLongitude: Double?,
minLatitude: Double?, maxLatitude: Double?,
minDepth: Double?, maxDepth: Double?) {
// Dates
self.startDate = startDate
self.endDate = endDate
// Magnitude Values
self.minMagnitude = minMagnitude
self.maxMagnitude = maxMagnitude
// Geographic Coordinates
self.minLongitude = minLongitude
self.maxLongitude = maxLongitude
self.minLatitude = minLatitude
self.maxLatitude = maxLatitude
// Depth Values
self.minDepth = minDepth
self.maxDepth = maxDepth
}
}
一个解决方案是显式地创建一个类型为 [Any]
的新数组,并且仅在 属性 不是 nil
时才将其添加到数组中。
public var nonNilProperties: [Any] {
let allProperties: [Any?] = [startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth]
var output = [Any]()
for property in allProperties {
if let nonNilProperty = property {
output.append(nonNilProperty)
}
}
return output
}
或者您可以使用更接近原始解决方案的 flatMap
(归功于@Leo Dabus)
public var nonNilProperties: [Any] {
return ([startDate, endDate, minMagnitude, maxMagnitude, minLongitude, maxLongitude, minLatitude, maxLatitude, minDepth, maxDepth] as [Any?]).flatMap { [=11=] }
}
测试用例:
let lastSearch = LastSearch(startDate: Date(), endDate: Date(), minMagnitude: 1.0, maxMagnitude: 5.0, minLongitude: nil, maxLongitude: nil, minLatitude: nil, maxLatitude: nil, minDepth: nil, maxDepth: nil)
print(lastSearch.nonNilProperties)
输出:
[2017-11-26 02:00:13 +0000, 2017-11-26 02:00:13 +0000, 1.0, 5.0]
这可行,但有点笨拙。根据您的具体情况,可能有更好的方法来构建您的数据。
第一个 nonNilProperties 不是 Any,它是 [Any](任意数组)。而且您不需要将每个 属性 都转换为 any,它会自动执行。其次,flatMap 不是您所需要的。使用地图。 flatMap 不会遍历元素,而是对整个数组进行操作。以下是一些示例:http://sketchytech.blogspot.ru/2015/06/swift-what-do-map-and-flatmap-really-do.html
正如 Leo Dabus 在评论中指出的那样,如果我不知道它们是什么,那么单独拥有非 nil 值是没有用的。也就是说,这就是我最终所做的:
在
我将此方法添加到我的 class:
func unwrap<T>(_ any: T) -> Any {
let mirror = Mirror(reflecting: any)
guard mirror.displayStyle == .optional, let first = mirror.children.first else {
return any
}
return unwrap(first.value)
}
然后,我创建了一个计算变量 return 一个 Dictionary
的非零值,使用 Mirror
.
var nonNilPropertyDict: [String: Any] {
let keys = Mirror(reflecting: self).children.flatMap { [=11=].label }
let values = Mirror(reflecting: self).children.flatMap { unwrap([=11=].value) as! AnyObject }
var dict = Dictionary(uniqueKeysWithValues: zip(keys, values))
var keysToRemove = dict.keys.filter{ dict[[=11=]] is NSNull }
for key in keysToRemove {
dict.removeValue(forKey: key)
}
return dict
}