私は、オプションのTの配列を非オプションのTの配列に変換できるようにする拡張機能をArrayに書き込もうとしています。
例えばこれは、次のような無料の関数として書くことができます。
func removeAllNils(array: [T?]) -> [T] {
return array
.filter({ $0 != nil }) // remove nils, still a [T?]
.map({ $0! }) // convert each element from a T? to a T
}
しかし、これを拡張機能として機能させることはできません。拡張機能はオプション値の配列にのみ適用されることをコンパイラに伝えようとしています。これは私がこれまでに持っているものです:
extension Array {
func filterNils<U, T: Optional<U>>() -> [U] {
return filter({ $0 != nil }).map({ $0! })
}
}
(コンパイルしません!)
汎用の構造体またはクラスに定義されている型を制限することはできません。配列はどの型でも機能するように設計されているため、型のサブセットで機能するメソッドを追加することはできません。型制約は、ジェネリック型を宣言するときにのみ指定できます
必要なものを達成する唯一の方法は、グローバル関数または静的メソッドを作成することです-後者の場合:
extension Array {
static func filterNils(array: [T?]) -> [T] {
return array.filter { $0 != nil }.map { $0! }
}
}
var array:[Int?] = [1, nil, 2, 3, nil]
Array.filterNils(array)
または、単にcompactMap
(以前はflatMap
)を使用します。これは、すべてのnil値を削除するために使用できます。
[1, 2, nil, 4].compactMap { $0 } // Returns [1, 2, 4]
Swift 2.0では、配列からnil値をフィルタリングするために独自の拡張機能を記述する必要はありません。配列を平坦化し、nilをフィルタリングするflatMap
を使用できます。
let optionals : [String?] = ["a", "b", nil, "d"]
let nonOptionals = optionals.flatMap{$0}
print(nonOptionals)
プリント:
[a, b, d]
2つのflatMap
関数があります。
1つのflatMap
は、上記の非nil値を削除するために使用されます。参照- https://developer.Apple.com/documentation/Swift/sequence/2907182-flatmap
他のflatMap
は結果を連結するために使用されます。参照- https://developer.Apple.com/documentation/Swift/sequence/2905332-flatmap
Swift 4を使用できるほど幸運なら、compactMap
を使用してnil値を除外できます。
array = array.compactMap { $0 }
例えば。
let array = [1, 2, nil, 4]
let nonNilArray = array.compactMap { $0 }
print(nonNilArray)
// [1, 2, 4]
Swift 2.0)以降、where
句を使用して、タイプのサブセットに対して機能するメソッドを追加することができます。この Appleフォーラムスレッド これは、配列のnil
値を除外するために使用できます。クレジットは@nnnnnnnnと@SteveMcQwarkに割り当てられます。
where
句はまだジェネリックをサポートしていないため(Optional<T>
)、プロトコルを介した回避策が必要です。
protocol OptionalType {
typealias T
func intoOptional() -> T?
}
extension Optional : OptionalType {
func intoOptional() -> T? {
return self.flatMap {$0}
}
}
extension SequenceType where Generator.Element: OptionalType {
func flatten() -> [Generator.Element.T] {
return self.map { $0.intoOptional() }
.filter { $0 != nil }
.map { $0! }
}
}
let mixed: [AnyObject?] = [1, "", nil, 3, nil, 4]
let nonnils = mixed.flatten() // 1, "", 3, 4
これはSwift 4:
protocol OptionalType {
associatedtype Wrapped
var optional: Wrapped? { get }
}
extension Optional: OptionalType {
var optional: Wrapped? { return self }
}
extension Sequence where Iterator.Element: OptionalType {
func removeNils() -> [Iterator.Element.Wrapped] {
return self.flatMap { $0.optional }
}
}
class UtilitiesTests: XCTestCase {
func testRemoveNils() {
let optionalString: String? = nil
let strings: [String?] = ["Foo", optionalString, "Bar", optionalString, "Baz"]
XCTAssert(strings.count == 5)
XCTAssert(strings.removeNils().count == 3)
let integers: [Int?] = [2, nil, 4, nil, nil, 5]
XCTAssert(integers.count == 6)
XCTAssert(integers.removeNils().count == 3)
}
}