Reputation: 2143
Adding an extension to Array, which returns the first Int or String is easy:
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
I can define a generic version, but I am not able to figure out how to call it because it does not take any parameter. Without a parameter, I can't specify the type!
extension Array {
func firstValueOfType<T>() -> T? {
return self.flatMap{$0 as? T}.first
}
}
// I can't figure out how to call this method!
I can work around it by adding a dummy parameter, but this is ugly.
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")
I'd appreciate if somebody could tell me how to call firstValueOfType function (or alternative way to define a generic function cleanly).
"Cannot explicitly specialize a generic function" is similar, but my problem is a bit more complicated because of Optional.
I've got a great answer from OOPer, which even includes the better implementation which uses lazy.filter, instead of 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")
Thank you very much for a very quick support!
Upvotes: 3
Views: 1345
Reputation: 5074
You can pass the type as an argument with T.Type
, like so:
extension Array {
func firstValue<T>(like type: T.Type) -> T? {
return self.flatMap{$0 as? T}.first
}
}
[1,2,3].firstValue(like: Int.self)
Upvotes: 3
Reputation: 47896
One way is assigning the result to a variable with explicit type.
let i: Int? = a1.firstValueOfType()
print(i) // Optional(3)
let s: String? = a1.firstValueOfType()
print(s) // Optional("abc")
Another is using as
:
print(a1.firstValueOfType() as Int?) // Optional(3)
print(a1.firstValueOfType() as String?) // Optional("abc")
Upvotes: 3