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

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

ただいまの
回答率

91.04%

  • Swift

    5895questions

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

  • iOS

    3351questions

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

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 127

Kenny

score 7

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

let myClasses = ["abc", "def", "ghi", "jkl", "mno"]

// この配列を2要素ずつに分割して3つの別々の配列に分割したい!
// この例ではString配列になっていますが、他のクラスでも使えるような形にしたいです。

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

あんまり綺麗じゃないですが

extension Array {

    func split(num: Int) -> [[Element]] {

        func divide<T>(num: Int, divided: [[T]], source: [T] ) -> ([[T]], [T]) {

            if source.isEmpty {
                return (divided, [])
            }

            if source.count <= num {
                return (divided + [source], [])
            }

            return divide(num: num,
                          divided: divided + [Array<T>(source[0..<num])],
                          source: Array<T>(source.dropFirst(num)))
        }

        let (divided, _) = divide(num: num, divided: [], source: self)
        return divided
    }
}

let myClasses = ["abc", "def", "ghi", "jkl", "mno"]

let splited = myClasses.split(num: 2)

追記

あまりにもパフォーマンスが悪すぎるので書き直しました。
多分O(N)ぐらいになってます。
複雑になったので説明コメント多めです。

extension Array {

    /// 配列を要素数が num の配列の配列にする
    ///
    /// let array = [1, 2, 3, 4, 5]
    /// let splited = array.split(num: 2)
    /// print(splited)
    /// // [[1, 2], [3, 4], [5]]
    func split(num: Int) -> [[Element]] {

        /// 配列を半分に分けて前半後半それぞれをもう一度半分に分ける
        /// これを要素数が num 以下になるまで繰り返す

        let count = self.count

        // 要素数が num 以下の時
        if count <= num {

            return [self]
        }
        // 要素数が 2 * num 以下の時
        if count <= num * 2 {

            return [Array<Element>(self[0..<num])]
                + [Array<Element>(self[num...])]
        }

        // 前半の要素数が num の整数倍になるように分割点を求める
        let splitPoint = Int(count / num / 2) * num

        switch splitPoint {

        case num:
            // 前半の要素数が num の時

            return [Array<Element>(self[0..<num])]
                + Array<Element>(self[num..<count]).split(num: num)

        case (num...):
            // 前半の要素数が num 以上の時

            return Array<Element>(self[0..<splitPoint]).split(num: num)
                + Array<Element>(self[splitPoint..<count]).split(num: num)

        default:
            // ここには到達しない

            fatalError("Not reachable")
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/06 03:25

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

    キャンセル

  • 2018/01/07 03:25

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

    キャンセル

0

まずはどのような愚直な方法でもよいので、実現できるコードを書くことが大事ではないでしょうか?配列を使うのでしょうから

(1) 配列に要素を追加するにはどうすればよい?
(2) 配列の要素数を調べるにはどうすればよい?
(3) 要素をひとつづつ処理するにはどうすればよい?

などなどを調べて書いてみると見えてくる気がします。

let a = ["a", "b", "c", "d", "e"]

func splitStringArray(_ a: [String], _ n: Int) -> [[String]] {
  var r: [[String]] = []
  var ia: [String] = []
  for e in a {
    if ia.count >= n {
      r.append(ia)
      ia = []
    }
    ia.append(e)
  }
  if ia.count > 0 {
    r.append(ia)
  }
  return r
}

print(splitStringArray(a, 2))  // [["a", "b"], ["c", "d"], ["e"]]

自分は、最初に挙げた(1)~(3)もうろ覚えというレベルなので、ググって書いてみました。おそらくはswiftに慣れた方ならもっとスマートに書けるのかも知れませんね。

しかし、不格好でもなんでもまずは動くものを書き、swiftの文法やクラスの使い方に慣れていった方がよいと思います。上記のようなものでもいいから書いてみているうちにだんだん苦労なく書けるようになっていくだろうと思います。自分が言語を学ぶ際にはそういうふうにして覚えていきました。最初のころにはずいぶんヘンテコなコードを書いたものですが、自分で色々書いたおかげで多少はましになった気がします。


なお、「String限定ではなくて任意の型を扱える」ように関数を書くには「ジェネリクス」というキーワードを調べると書き方がわかる気がします。「swift generics」で検索するとヒットしましたので。しかしそれを書くのは基本的な論理が組めてからでも遅くないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 91.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    5895questions

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

  • iOS

    3351questions

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