以前、so でみつけたこういうコード。
extension Array where Element: Collection {
func toD1() -> [Element.Element] {
return self.flatMap { $0 }
}
}
👉 【 Swift 】2次元配列と1次元配列の相互変換 🤔 ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://android.benigumo.com/20240211/handle-array/)
なんとなく「Collection」 の部分が気持ち悪かったのであれこれやってみます。
■ お題
2次元配列を平坦化します。
let data = [
["あ", "い", "う"],
["え", "お"]
]
print(data.flatMap { $0 })
// ["あ", "い", "う", "え", "お"]
print(Array(data.joined()))
// ["あ", "い", "う", "え", "お"]
これを extension 化しようとして、
extension Array {
var flattened: [String] {
flatMap { $0 }
}
}
![](https://i0.wp.com/android.benigumo.com/wp-content/uploads/2024/02/sc-2024-02-23-at-16.33.21.png?ssl=1)
Instance method 'flatMap' requires that 'Element' conform to 'Sequence'
とエラーがでるとこからスタートです。
■ やってみた
ドキュメントや先人の記事を読んでおきます。
👉 Element | Apple Developer Documentation ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://developer.apple.com/documentation/swift/sequence/element)
👉 Array | Apple Developer Documentation ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://developer.apple.com/documentation/swift/array)
👉 [Swift]Array型 #Swift - Qiita ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://qiita.com/makopy_inside/items/71f385f67ca215da5c47)
型や制約の記述を確認しながら進みます。
extension Array where Element == Array<String> {
var flattened: [String] {
// Array(joined()) // Cannot convert return expression of type 'Array<Array<String>>' to return type '[String]'
// joined().map { $0 } // OK
// Array<String>(joined()) // OK
// [Element.Element](joined()) // OK
// [String](joined()) // OK
flatMap { $0 } // OK
}
extension [[String]] where Element == [String] {
var flattened: [String] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
extension Array where Element == [String], Element.Element == String {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
ここで、制約を先祖のプロトコルのみにします。
extension Array where Element: Collection {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
揃えたほうが良さげです。
extension Collection where Element: Collection {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
スッキリしました !
Sequence でもいけるんですね。
extension Sequence where Element: Sequence {
var flattened: [Element.Element] {
flatMap { $0 }
}
}
// ["あ", "い", "う", "え", "お"]
👉 誰もが知りたいSequenceとCollectionのすべて ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://academy.realm.io/jp/posts/try-swift-soroush-khanlou-sequence-collection/)
ちなみに、元の配列に nil を混ぜると、
let data = [
["あ", nil, "う"],
["え", "お"]
]
上手に処理してくれてますね!
// [Optional("あ"), nil, Optional("う"), Optional("え"), Optional("お")]
■ まとめ
プロトコルと型。
よく分かってませんが
なんだか深そうです。
そういえば、どこかに書いてました、
プロトコルを使用することによって得られる柔軟性と、特定の型のメソッドの作成の容易さのバランス
というようなフレーズ。
ありがとうございます。
どこか継承グラフみれるとことかあるのでしょうか ? 独自に書き出さずに。
👉 Dash for macOS - API Documentation Browser, Snippet Manager - Kapeli ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://kapeli.com/dash)
👉 realm/jazzy: Soulful docs for Swift & Objective-C ![hatena-bookmark](https://b.hatena.ne.jp/entry/image/https://github.com/realm/jazzy)