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

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

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

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

Q&A

解決済

1回答

576閲覧

swift タプル型の長所短所

L85A2

総合スコア60

Swift

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

0グッド

0クリップ

投稿2018/08/31 03:38

こないだ初めてswiftでタプル型というものを知りました。
使い方はなんとなくわかったのですが長所や短所が明確にわかりません。
長所と短所はなんでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

(以下fuzzballさんのアドバイスを受けてからの修正回答になります)

タプルと配列を比較してメリットデメリットをみていきます。

が、最初に特殊なAny型について少々説明をします。
Swiftには色々な型がありますが特殊な型としてAny型というものがあります。このAny型で宣言された変数や定数はどんな型の値でも入れられるようになります。ですがどんな値でも入れられる、ということは危険性も孕んでおり中身が何なのかが簡単には分からない、という反面も持ち合わせています。ですのでこんなことも可能です。

swift

1var anyTypeValue: Any = 1 2anyTypeValue = "String" 3anyTypeValue = 10.5

このAny型を使った配列というのもあり

swift

1let anyTypeArray: [Any] = [1, "string", 100000.5]

こんな風に色々な型の値が入った配列も作れてしまいます。この配列の中の値は全てAny型の値なため実際は何型なのか分かりません。配列の中身が何型か分からない、ということはこの配列を扱うのが難しい、というデメリットにつながります。
(fuzzballさんのコメントを受けて再度修正です)
anyTypeArrayの中身を添字で取り出した時、anyTypeArray[0]はInt型、anyTypeArray[1]はString型、anyTypeArray[2]はDouble型の値となります。ただanyTypeArrayの中身を取り出すまで何型か分からない、ということはこの配列を扱うのが難しい、というデメリットにつながります。

一方タプルでは

swift

1let tuple = (100, "hoge", 5.5)

色々な型の値が入ったタプルというものが簡単に出来ます。こちらはタプルの中の値の型はわかっており、上記の例だとInt, String, Double型になります。
ここでfuzzballさんのコメントを引用させていただくと

・タプルは「違う型で複数の値を格納」するのが簡単

と言えます。これがタプルのメリットです。

また配列は配列操作を行えますが、タプルではそれができません。
配列操作とは.enumarated.map.foreach等配列の中身各々に対して何らかの操作を行うものです。詳しくは配列操作で検索すれば色々出てきますので割愛させていただきます。

下記は一例です。

swift

1stringArray.map{print($0)} //OK この$0はstringArrayの配列の中身一つ一つを表しています。 2tuple.map{print($0)} //NG

配列操作はいくつかを連続して行うこと出来、一つの操作が終わった結果をいちいち定数や変数に入れる必要がありません。これは配列が配列である大きなメリットです。

タプルと配列の似ている点として、どちらも(雑な表現ですが)数字を使って取り出すことができます。上記の二例をここでまた引っ張り出しますが

swift

1let anyTypeArray: [Any] = [1, "string", 100000.5] 2let tuple = (100, "hoge", 5.5) 3print(anyTypeArray[0] //1 4print(tuple.0) //100

こんな感じで取り出せます。

また両方のメリットを享受するために

swift

1let tupleArray: [(Int, String)] = [(0, "あいうえお"), (1, "かきくけこ")]

なんて特定のタプルの配列を作ることもあります(この場合someArray.enumarated()とした方が良いですが分かりやすさのためこんな形にしています)。

投稿2018/08/31 06:11

編集2018/08/31 09:40
xAxis

総合スコア1349

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

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

L85A2

2018/08/31 06:19

回答ありがとうございます。違う型で複数の値を格納したいときに使えばよさそうですね。
xAxis

2018/08/31 06:27

そういう使い方もよくします。ただ一つのタプルにあまりに多くの値を入れすぎるとコードがカオスになっちゃうことがよくあるので、ある程度数を限定した方が良いでしょう。
fuzzball

2018/08/31 06:34

なぜAny型を除外したのでしょうか? 除外しておいて「配列は特定の型を限定して入れられる」というのはちょっとおかしいような。 さらに「(タプルは)違う型で複数の値を格納したいときに使えばよさそうですね」みたいなコメント付いてるし‥。
xAxis

2018/08/31 07:45

Any型を扱わなかった理由はキャスト、Any型を扱うことの難しさ、それからジェネリック型まで言及したくなかったからです。初心者マークがついていますし、そんなにたくさん言及しても理解がとっちらかるだけではないかと。それならタプルと配列の簡単なメリット、デメリットを比較、そして配列操作に絞った方が分かりやすいのではと思いました。また ""ジェネリック型を使うことで、型安全性を犠牲にすることなく柔軟性の高い関数を書けます。Any型を使うのであれば、その責任は自分自身で負わなければなりません。"" 引用元 Chris Eidhof・Florian Kugler・Wouter Swierstra(2016) 『Functional Swift』(和田祐一郎訳)objc. でもあるようにAny型を扱うのは大変であるというのが自分の現状の認識です。ですから何が入るか分からないAny型は触れないで済むなら触れたくない型です。以上がAny型に言及しなかった理由になります。 > 除外しておいて「配列は特定の型を限定して入れられる」というのはちょっとおかしいような。 これはAny型に言及しないのであれば間違いではないのではないでしょうか。Any型以外の型の配列を作るのであればそれは何らかの型の値のみが入れられる配列です。おかしいというのはどの点においておかしいかお教えいただけたらと思います。 > (タプルは)違う型で複数の値を格納したいときに使えばよさそうですね これは自分のスタンスにおいても同意です。現に配列をenumeratedすれば型の違うoffsetとelementのタプルが出来上がるのはよくあることですし、型の違う少量の定数をまとめておいきたい時にも自分はタプルを使います。多くなった場合は構造体に切り替えます。ですので型の違う複数の値を格納したいときにタプルを使うのは問題ではないと認識しています。 タプルに関してはもちろん他の使い方もあるかもしれません。まだまだ未熟ゆえその他の使い方というのを存じ上げません。もしよろしければこちらの点に関しても知見をご教授いただけたら幸いです。
fuzzball

2018/08/31 08:06

配列は「違う型で複数の値を格納出来ない」と誤解していそうなのが心配で。 ・タプルは「違う型で複数の値を格納」するのが簡単 ・配列は「「違う型で複数の値を格納」するのが難しい(面倒) くらいの表現の方が良かったかなぁと。 ただ、違う型を入れる場合の比較対象は、配列ではなく構造体のような気もしますが。 大雑把に「タプルは何かとお手軽です」ということに異論はありません。(最初、そう回答しようと思ったのですがやめましたw)
kakajika

2018/08/31 08:20 編集

タプルはむしろ構造体に近いもの(厳密に言うと、無名の構造体)という認識なので、配列と比較されているのはちょっと不思議に感じました。(質問にはその点明示されていないので、そういう捉え方もできますね)
xAxis

2018/08/31 09:15

>>fuzzballさん これは > 配列は「違う型で複数の値を格納出来ない」と誤解していそうなのが心配で。 > ・タプルは「違う型で複数の値を格納」するのが簡単 > ・配列は「「違う型で複数の値を格納」するのが難しい(面倒) とした方がより適切な上に分かりやすい表現だと思いました。ご教授ありがとうございます。回答を見直します。 > 大雑把に「タプルは何かとお手軽です」ということに異論はありません。(最初、そう回答しようと思ったのですがやめましたw) これは完全に同意ですw >>fuzzballさん >>kakajikaさん > 違う型を入れる場合の比較対象は、配列ではなく構造体のような気もしますが。 > タプルはむしろ構造体に近いものという認識 お二人の認識と自分の認識が違うことに関して今すごく新鮮で楽しい気持ちです。 何故私が構造体ではなくタプルと配列を比較したかというとタプルや配列の中身を取り出す時、タプルではtuple.0、配列ではarray[0]のように(雑な表現になりますが)数字での取り出しが可能であるからです。 私の認識では数字で取り出せる、という共通項があるがゆえ比較対象としてより適切だと思いタプルと配列の比較を比較してみました。あとは個人的に配列操作に少しだけでも言及しておきたかった、という欲もあったりします(Any型をバッサリ切っておいてこんなことを言うのもお門違いなのは重々承知なのですが・・・)。
fuzzball

2018/08/31 09:27

念のため書いておきますが、anyTypeArray[n] の型は Any ではなく、[0]から順に Int, String, Double となります。あくまで anyTypeArray が [Any]型ということです。
xAxis

2018/08/31 09:42

>>fuzzballさん これは自分の理解不足でした。勉強になりました!ありがとうございます!! >> Ceratophrysさん 回答が二点三転してしまい混乱させてしまったかもしれません。ごめんなさい。
L85A2

2018/08/31 09:47

>> xAxisさん いえいえ。こういう討論ができるということはむしろ喜ばしいことだと思います。 おかげで色々なことが学べました。 >>fuzzballさん >>kakajikaさん ありがとうございます。 無名の構造体やanyTypeArray が [Any]型はかなり勉強になりました。
kakajika

2018/08/31 09:49 編集

> タプルではtuple.0、配列ではarray[0]のように... たしかに、その点で見ると似ているかもしれません。ただ、タプルは要素に名前をつけること (例: let point = (x: 0.0f, y: 0.0f))が可能ですし、他の言語では名前省略時のアクセス方法は0, 1, ...でなかったりします。
fuzzball

2018/08/31 09:57

>>xAxisさん ちょっと、すみません。もしかしたら正しくないのかも。 print(type(of: anyTypeArray[0])) //=> Int let i = anyTypeArray[0] print(type(of: i)) //=> Int となって Int と認識されるのですが、 let i: Int = anyTypeArray[0] だと、Cannot convert value of type 'Any' to specified type 'Int' というエラーが出ます。(あれ?Anyなの?) こういう場合 anyTypeArray[0] は何型ということになるんでしょうか‥。 >>kakajikaさん Pythonのタプルは配列(リスト)そのものですね。
xAxis

2018/08/31 09:57

>> Ceratophrysさん そう言っていただけると嬉しいです。ありがとうございます! >> kakajikaさん > let point = (x: 0.0f, y: 0.0f) これだと無名の構造体と同じ認識ですね。 > 他の言語では名前省略時のアクセス方法は0, 1, ...でなかったりします これは知りませんでした。勉強になります! 最初は比較対象が構造体であるというのは上記のバイアスがかかっている自分の頭ではよく分からなかったのですが、今ではタプルと配列を比較するというのもおかしな風に取られるのも理解できました。ありがとうございました!
xAxis

2018/09/03 03:55 編集

>> fuzzballさん 自分も ""let const = anyTypeArray[0] として予測変換でconstを出した時Intとなっていたのでfuzzballさんのおっしゃる通りだ!って思ってたのですが"" 上記の囲ってある部分は間違いです。予測変換で出てくる型はAny型でした。何を寝ぼけてたのか。。。失礼しました。 最後の let i: Int = anyTypeArray[0] これは確認してませんでした。 これどういうことなんでしょう。 挙動としては代入される前はAny型で代入された後はInt型という風にみえますから、仮説としては代入以前ではAny型、代入以後はInt型ということでしょうか。 しかしそれってありなんでしょうかね?
fuzzball

2018/09/02 23:54

ただの思いつきですが、ビルド時は型が分からずAny、実行時は型が確定するのでIntかな、と休み明けの頭でぼんやりと。
xAxis

2018/09/03 03:59

上記のコメント訂正です。 自分も色々と触ってみたのですが結局よくわかりませんでした。なのでfuzzballさんの > ビルド時は型が分からずAny、実行時は型が確定するのでInt というコメントを見て、確証もないですがそういうものかもしれないなと思いました。 あとAnyってよくみると予約語なんですね。型のはずなのに。それではじめて知ったのですが予約語ってJump to Definition出来ないんですね。だからどうなってるか中身をみることも出来ず。 ただ以下リンクでAnyは単なる空のprotocolだという話も https://qiita.com/ezura/items/d011c9b13c70055b6e57
xAxis

2018/09/03 04:08

あとチラ裏なお話ですがここ最近Swiftで今回みたいに細かいところがよく分からない、みたいな件がたまにあります。こういう疑問を解決するにはSwift開発した人とかに直接聞いてみるしかないんでしょうかね。それとも単にまだまだ勉強不足なのか。。。
fuzzball

2018/09/03 04:52

そこはソースコード読むところですよw
xAxis

2018/09/03 05:10

ぐぬぬw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問