Swift3を使って、配列を特定要素数ずつの細かい配列に分割する方法を教えてください。
Swift
1let myClasses = ["abc", "def", "ghi", "jkl", "mno"] 2 3// この配列を2要素ずつに分割して3つの別々の配列に分割したい! 4// この例ではString配列になっていますが、他のクラスでも使えるような形にしたいです。
どなたかアドバイスいただけますと幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
寝ながらスマホという環境なのでコードは提示できないのですが、Swift3にはそのような機能を持つ関数は用意されていないみたいです。自分で実装する必要があります。
実装の方針としては、まず二次元配列を作成し、そこにmyClasses配列の要素を代入(もしくは追加)していくという実装になると思います。
myClasses配列のインデックスをiとすると、このiを特定要素数で割ったときの商と余りが、二次元配列のインデックスになります。
実装できますでしょうか?
投稿2018/01/05 17:14
編集2018/01/05 17:18総合スコア75
0
ベストアンサー
あんまり綺麗じゃないですが
swift
1extension Array { 2 3 func split(num: Int) -> [[Element]] { 4 5 func divide<T>(num: Int, divided: [[T]], source: [T] ) -> ([[T]], [T]) { 6 7 if source.isEmpty { 8 return (divided, []) 9 } 10 11 if source.count <= num { 12 return (divided + [source], []) 13 } 14 15 return divide(num: num, 16 divided: divided + [Array<T>(source[0..<num])], 17 source: Array<T>(source.dropFirst(num))) 18 } 19 20 let (divided, _) = divide(num: num, divided: [], source: self) 21 return divided 22 } 23} 24 25let myClasses = ["abc", "def", "ghi", "jkl", "mno"] 26 27let splited = myClasses.split(num: 2)
追記
あまりにもパフォーマンスが悪すぎるので書き直しました。
多分O(N)ぐらいになってます。
複雑になったので説明コメント多めです。
swift
1extension Array { 2 3 /// 配列を要素数が num の配列の配列にする 4 /// 5 /// let array = [1, 2, 3, 4, 5] 6 /// let splited = array.split(num: 2) 7 /// print(splited) 8 /// // [[1, 2], [3, 4], [5]] 9 func split(num: Int) -> [[Element]] { 10 11 /// 配列を半分に分けて前半後半それぞれをもう一度半分に分ける 12 /// これを要素数が num 以下になるまで繰り返す 13 14 let count = self.count 15 16 // 要素数が num 以下の時 17 if count <= num { 18 19 return [self] 20 } 21 // 要素数が 2 * num 以下の時 22 if count <= num * 2 { 23 24 return [Array<Element>(self[0..<num])] 25 + [Array<Element>(self[num...])] 26 } 27 28 // 前半の要素数が num の整数倍になるように分割点を求める 29 let splitPoint = Int(count / num / 2) * num 30 31 switch splitPoint { 32 33 case num: 34 // 前半の要素数が num の時 35 36 return [Array<Element>(self[0..<num])] 37 + Array<Element>(self[num..<count]).split(num: num) 38 39 case (num...): 40 // 前半の要素数が num 以上の時 41 42 return Array<Element>(self[0..<splitPoint]).split(num: num) 43 + Array<Element>(self[splitPoint..<count]).split(num: num) 44 45 default: 46 // ここには到達しない 47 48 fatalError("Not reachable") 49 } 50 } 51}
投稿2018/01/05 18:14
編集2018/01/06 19:18総合スコア3384
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/01/06 18:25
0
まずはどのような愚直な方法でもよいので、実現できるコードを書くことが大事ではないでしょうか?配列を使うのでしょうから
(1) 配列に要素を追加するにはどうすればよい?
(2) 配列の要素数を調べるにはどうすればよい?
(3) 要素をひとつづつ処理するにはどうすればよい?
などなどを調べて書いてみると見えてくる気がします。
swift
1let a = ["a", "b", "c", "d", "e"] 2 3func splitStringArray(_ a: [String], _ n: Int) -> [[String]] { 4 var r: [[String]] = [] 5 var ia: [String] = [] 6 for e in a { 7 if ia.count >= n { 8 r.append(ia) 9 ia = [] 10 } 11 ia.append(e) 12 } 13 if ia.count > 0 { 14 r.append(ia) 15 } 16 return r 17} 18 19print(splitStringArray(a, 2)) // [["a", "b"], ["c", "d"], ["e"]]
自分は、最初に挙げた(1)~(3)もうろ覚えというレベルなので、ググって書いてみました。おそらくはswiftに慣れた方ならもっとスマートに書けるのかも知れませんね。
しかし、不格好でもなんでもまずは動くものを書き、swiftの文法やクラスの使い方に慣れていった方がよいと思います。上記のようなものでもいいから書いてみているうちにだんだん苦労なく書けるようになっていくだろうと思います。自分が言語を学ぶ際にはそういうふうにして覚えていきました。最初のころにはずいぶんヘンテコなコードを書いたものですが、自分で色々書いたおかげで多少はましになった気がします。
なお、「String限定ではなくて任意の型を扱える」ように関数を書くには「ジェネリクス」というキーワードを調べると書き方がわかる気がします。「swift generics」で検索するとヒットしましたので。しかしそれを書くのは基本的な論理が組めてからでも遅くないと思います。
投稿2018/01/05 17:32
総合スコア18394
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。