質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

3回答

4660閲覧

配列を特定要素数ずつの細かい配列に分割する方法

_CHO

総合スコア16

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/01/05 16:14

編集2018/01/05 16:14

Swift3を使って、配列を特定要素数ずつの細かい配列に分割する方法を教えてください。

Swift

1let myClasses = ["abc", "def", "ghi", "jkl", "mno"] 2 3// この配列を2要素ずつに分割して3つの別々の配列に分割したい! 4// この例ではString配列になっていますが、他のクラスでも使えるような形にしたいです。

どなたかアドバイスいただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

寝ながらスマホという環境なのでコードは提示できないのですが、Swift3にはそのような機能を持つ関数は用意されていないみたいです。自分で実装する必要があります。

実装の方針としては、まず二次元配列を作成し、そこにmyClasses配列の要素を代入(もしくは追加)していくという実装になると思います。
myClasses配列のインデックスをiとすると、このiを特定要素数で割ったときの商と余りが、二次元配列のインデックスになります。

実装できますでしょうか?

投稿2018/01/05 17:14

編集2018/01/05 17:18
pngnshny

総合スコア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
MasakiHori

総合スコア3384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MasakiHori

2018/01/05 18:25

すいみません。 これO(N^2)ぐらいありますね。 動くけど使い物にならないと思います。 忘れてください
MasakiHori

2018/01/06 18:25

あまりにもひどかったのでパフォーマンスを向上させたものを追記しました。
guest

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

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問