向Array添加扩展,返回第一个Int或String很简单:
extension Array {
func firstInt() -> Int? {
return self.flatMap{$0 as? Int}.first
}
func firstString() -> String? {
return self.flatMap{$0 as? String}.first
}
}
let a1:[AnyObject?] = [nil, "abc", 3, 4]
let a2:[AnyObject?] = [nil, [3], [ "foo":"bar" ]]
print(a1.firstInt()) // Optional(3)
print(a2.firstInt()) // nil
print(a1.firstString()) // Optional("abc")
print(a2.firstString()) // nil
我可以定义一个通用版本,但我无法弄清楚如何调用它,因为它不带任何参数。没有参数,我无法指定类型!
extension Array {
func firstValueOfType<T>() -> T? {
return self.flatMap{$0 as? T}.first
}
}
// I can't figure out how to call this method!
我可以通过添加一个虚拟参数来解决它,但这很难看。
extension Array {
func firstValueLike<T>(_:T) -> T? {
return self.flatMap{$0 as? T}.first
}
}
let a1:[AnyObject?] = [nil, "abc", 3, 4]
print(a1.firstValueLike(1)) // Optional(3)
print(a1.firstValueLike("")) // Optional("abc")
如果有人能告诉我如何调用firstValueOfType函数(或者干净地定义泛型函数的替代方法),我会很感激。
“无法明确专门化泛型函数”是类似的,但由于Optional,我的问题有点复杂。
我从OOPer得到了一个很好的答案,它甚至包括使用lazy.filter而不是flatMap的更好的实现。
extension Array {
func firstValueOfType<T>() -> T? {
return self.lazy.filter {$0 is T}.first as? T
}
}
let a1:[AnyObject?] = [nil, "abc", 3, 4]
print(a1.firstValueOfType() as Int?) // Optional(3)
print(a1.firstValueOfType() as String?) // Optional("abc")
非常感谢您提供快速支持!
答案 0 :(得分:3)
一种方法是将结果分配给具有显式类型的变量。
let i: Int? = a1.firstValueOfType()
print(i) // Optional(3)
let s: String? = a1.firstValueOfType()
print(s) // Optional("abc")
另一个是使用as
:
print(a1.firstValueOfType() as Int?) // Optional(3)
print(a1.firstValueOfType() as String?) // Optional("abc")
答案 1 :(得分:2)
您可以将类型作为参数传递给T.Type
,如下所示:
extension Array {
func firstValue<T>(like type: T.Type) -> T? {
return self.flatMap{$0 as? T}.first
}
}
[1,2,3].firstValue(like: Int.self)