概要
前回に続き、swift学習のまとめです!
今回は、配列についてまとめてみます。
書き方だけでなく基本的な使い方やSwiftならではの関数などもなるべく載せています。
■前回
Swiftの超基本的な書き方をObjective-cと比較しながらまとめる
http://qiita.com/kkoide1332/items/0d05a90df2bb5e9571fb
配列宣言
// 配列宣言
NSArray *array = @[@"value1", @"value2", @"value3"];
// 配列へのアクセス
NSString *array0 = array[0];
// 配列宣言
var array = ["value1","value2","value3"]
// 以下のように、入る中身の型を明示的に指定することが出来ます
var array:[String] = ["value1","value2","value3"]
// letをつけると操作が出来ないimmutableな配列になります
let array:[String] = ["value1","value2","value3"]
// 配列へのアクセス
var array0 = array[0]
ポイント
・Swiftでは配列の中身を明示的に指定出来る
・immutableかどうかはvar/letで使い分ける(Objective-cだとNSArray/NSMutableArrayでしたよね)
・SwiftではArrayとNSArrayがある
ArrayとNSArrayの違い
似ているようで違います。大きな違いは2つあります。
1.使えるメソッドが違う
最初、普通に以下のようなコードを書きたかったのですがメソッドが無かったために
書けませんでした。。
// 配列宣言
var array = ["value1","value2","value3"]
array.objectAtIndex(0) ←Array型にobjecAtIndexは無い!
Array型ではobjectAtIndexやenumerateObjectsUsingBlockなど、Objective-cでよく使っていたメソッドが使えないです。。
また関数名も微妙に違っていたり(動きは同じなのですが)するので、あれ、同じのがない!?となるかもしれません。
2.参照渡しか値渡しか
もう1つの違いは、NSArrayは参照渡しであり、Arrayは値渡しです。
以下のサンプルをご覧ください。
var array1:NSMutableArray = ["value1","value2","value3"]
var array2 = array1
array1.removeAllObjects() // array1の要素を全部消してみる
print(array2) // 参照渡しのため、array2はいじっていないのに空配列になります
var array1 = ["value1","value2","value3"]
var array2 = array1
array1.removeAll() //
print(array2) // 値渡しのため、["value1","value2","value3"]が表示されます
アドレスを渡すか値をコピーしているだけかの違いですね。
これを知らずに使っていると思わぬ所で値が変わってしまう可能性があるので注意ですね。
Array系のメリットとしては宣言時に型を指定出来るので安全に使うことが出来ます。
入っている中身の型を保証したい時はArray系を使うと良さそうです。
ちなみにArrayとNSArrayは以下のように変換することが出来ます。
//ArrayからNSArray
var array1 = ["value1","value2","value3"]
var array2:NSArray = NSArray(array: array1) // NSArrayを作ってあげる
array2.objectAtIndex(0) // これでいつも使えるメソッドが使えます
//NSArrayからArray
var array3: [String] = array2 as! [String] // 強制ダウンキャスト(あまりやりかたとしてはよくないかも、、)
print(array3[0])
配列の便利関数たち
Swiftでこれはいい!と思ったのは以下の配列操作関数が標準であることです。
・map
・filter
これらは、Objective-cだと標準ではなかったですね。
ObjectiveSugarというOSSではあって、よく使っていた身としてはとても嬉しいです。
これらを使えるとシンプルに配列操作が出来ます!
map
配列の値に特定操作をして、そのまま配列を返します。
配列が帰ってくるのが重要です。
かんたんな例だと、[1,2,3]という配列があったとして、それに全て+1をして新しい配列にしたい時とかですね。
何にも考えないでべたーっと書くと以下のような感じになるとおもいます。
var array = [1,2,3]
var array2:[Int] = []
for var a in array {
a++
array2.append(a)
}
print(array2) // [2, 3, 4]
他にもかしこい書き方はあると思います、が!
mapを使うとこんな感じにかけます。
var array = [1,2,3]
var array2 = array.map{$0 + 1} // [2, 3, 4]
超シンプル!かこいい!
イメージとしてはmapは引数にクロージャ(blocksみたいなもの)を取っているので、
arrayに対する処理を{ }内(今回なら足し算)を書くって感じですね。
ちなみに上記はかなり省略した形でして、ちゃんと書くと下のようになります。
var array = [1,2,3]
var array2 = array.map { (var a:Int) -> Int in
return a + 1
}
上の形から、以下の書かなくても大丈夫なものを省いていくと最初の形なります。
・returnは書かなくても良い
・型(上記の例だとInt)は型推論があるので書かなくても良い
・クロージャの引数は$0,$1,$2→第1引数の値,第2引数の値,第3引数のようにかける
短すぎるのも可読性が下がる可能性がありますが、慣れてくると
array.map{$0 + 1}のような書き方でぱっと分かるしシンプルで良いかなと思います。
(書きやすいし覚えやすいのも個人的には好きですw)
filter
配列の中身で特定条件を満たしていない値を消したのち、配列を返します。
名前の通りですね。
var array = [1,2,3]
var array2 = array.filter {$0 % 2 == 0}
print(array2) // [2]
これも省略形で覚えるのが早くて楽そうですね。
mapとfilterの合わせ技!
こんなこともできます。
var array = [1,2,3]
var array2 = array.filter{$0 % 2 == 0}.map{$0 + 1}
print(array2) // [3]
1.[1,2,3]の中から2で割り切れるものだけにフィルターする
2.そのフィルターをかけた配列の中身に1を足す
って感じですね。
結局array.filterの返り値は配列なのでそのままmapを繋げられる、といった感じです。
面倒な処理が1行でかけたりシンプルにかけるのはいいですよね!
まとめ
ArrayとNSArrayの違いなど色々とObjective-cとの違いに戸惑いましたが、
便利な関数や型指定などいろんな利点もあるので
是非使う場所を見極めて積極的に使えるところは使っていこうと思います><
他にもこんな便利なやり方もあるよ、これは違うよ、などあればコメント是非ください!