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

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

ただいまの
回答率

89.63%

swiftの関数で引数によって次元の違う配列を返す方法はありますか?

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,159

hi_ro_kun

score 5

配列の宣言をする際に、条件によって次元の違う配列を戻り値としたいケースがあります。
しかし、関数の実装時に戻り値の配列の次元を決められてしまっているため、以下のような
テストケースの場合、コンパイルエラーとなり、思うように動作してくれません。
このようなケースで上手く動くようなプログラムは書けるのでしょうか?
戻り値の型推論ができると聞き、クロージャの説明を読んでみましたが、今ひとつピンと
きません。もし何かしらの方法があるのであればご教授していただけないでしょうか。

func test(gotit: Bool) -> [Int] { return gotit ? [[1,2,3],[4,5,6]] : [1,2,3,4,5,6] }

追記(ご指摘に対する対応)
詳細を説明せず、大変失礼いたしました。 実は、C++の得意な友人より、多次元配列の宣言が面倒な言語は 使う気になれないとバカにされ、何とか関数実装できないかと考え、 以下のような関数を作成したのですが、同じ関数で違う次元の 配列を返すことができればと思い相談させていただきました。 

func Array1<T>(index: [Int], rV: T) -> [T] { return [T](count: index[index.count-1], repeatedValue: rV) } 
func Array2<T>(index: [Int], rV: T) -> [[T]] { return [[T]](count: index[index.count-2], repeatedValue: Array1(index, rV: rV)) } 
func Array3<T>(index: [Int], rV: T) -> [[[T]]] { return [[[T]]](count: index[index.count-3], repeatedValue: Array2(index, rV: rV)) } 

var sw: [[[Bool]]] = Array3([2,3,2], rV: true) 
print(sw) 
// [[[true, true], [true, true], [true, true]], [[true, true], [true, true], [true, true]]] 

var dbl: [[[Double]]] = Array3([2,2,3], rV: Double(0.0)) 
print(dbl) 
// [[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]]
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • Stripe

    2016/03/01 23:43

    その関数の呼び出し元では、その戻り値をどのように扱うんですか?

    キャンセル

  • hi_ro_kun

    2016/03/02 00:02

    詳細を説明せず、大変失礼いたしました。
    実は、C++の得意な友人より、多次元配列の宣言が面倒な言語は
    使う気になれないとバカにされ、何とか関数実装できないかと考え、
    以下のような関数を作成したのですが、同じ関数で違う次元の
    配列を返すことができればと思い相談させていただきました。

    func Array1<T>(index: [Int], rV: T) -> [T] { return [T](count: index[index.count-1], repeatedValue: rV) }
    func Array2<T>(index: [Int], rV: T) -> [[T]] { return [[T]](count: index[index.count-2], repeatedValue: Array1(index, rV: rV)) }
    func Array3<T>(index: [Int], rV: T) -> [[[T]]] { return [[[T]]](count: index[index.count-3], repeatedValue: Array2(index, rV: rV)) }

    var sw: [[[Bool]]] = Array3([2,3,2], rV: true)
    print(sw) // [[[true, true], [true, true], [true, true]], [[true, true], [true, true], [true, true]]]

    var dbl: [[[Double]]] = Array3([2,2,3], rV: Double(0.0))
    print(dbl) // [[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]]

    キャンセル

  • Stripe

    2016/03/02 00:16

    ん??
    test()関数はどこへ行ったのですか?
    そのArray1()、Array2()、Array3()は、今回の質問とどのような関係があるんですか?

    キャンセル

  • hi_ro_kun

    2016/03/02 00:29

    わかりにくくてすみません。test()関数そのものにそれほど意味はなく、一つの関数で、条件により、一次元配列、二次元配列など、異なる次元の配列を戻り値として返せるのかどうかを質問するためにシンプルに必要部分を抜き出したものとご理解ください。
    また、Array1()、Array2()、Array3()に関しては、多次元配列の宣言の際に記述をシンプルにするための関数となっています。Array2()は二次元配列の、Array3()は三次元配列の宣言及び初期化を行います。引数 index: [Int] は各次元の要素数を、rVは初期値となっています。
    現状の仕様では、二次元配列を使用する場合はArray2()を、三次元配列を使用する場合はArray3()を呼び出すため、もっとスマートにならないかと考えています。言葉足らずであればすみません。

    キャンセル

回答 1

checkベストアンサー

0

関数の戻り値の型をAnyにすれば、動的にどんな値でも返せます。
ただし、呼び出し元でキャストしないと、その値にアクセスできません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/02 01:23

    コンパイルエラーが出ず、コンパイルできました。
    ありがとうございます。

    なお、下記のコードより呼び出したところ、型キャストがうまくいってない?ためか、
    こちらでコンパイルエラーとなりました。配列の型キャストの方法が間違っているのでしょうか。

    var tbl: [[[[[Int]]]]] = [[[[[Int]]]]](ArrayAll([2,2,2,2,2], d: 5, rV: 1))
    print(tbl)

    キャンセル

  • 2016/03/02 01:32

    キャストには、as?を使ってください。
    if let a = ArrayAll([2,2], d: 2, rV: 11) as? [Any] {
    print(a)
    if let b = a[0] as? [Any] {
    print(b)
    if let c = b[0] as? Int {
    print(c)
    }
    }
    }

    キャンセル

  • 2016/03/02 01:44

    うまくいきました!!
    ありがとうございました。
    as? や Any など使用したことのない機能を使う機会に恵まれ、
    また一つ成長できたように思います。
    貴重なお時間を割いてきただき、ありがとうございました。

    キャンセル

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

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

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