iOS
Swift

Swiftらしいコーディングを学ぶ 「CollectionType」

More than 1 year has passed since last update.


はじめに

以前はobjcでiOS開発する機会が多かったのですが、最近SwiftでiOS開発をする機会が多いので、Swiftらしいコーディングをしていくために学んだことをまとめていきたいと思います。何か気になることや、もっとよく書けるみたいな意見があれば気軽にコメントお願いします。今回はCollectionTypeに準拠する配列や辞書についてまとめました。


Collection Types

CollectionType Protocol Referenceを見てみるとArray, Set, DictionaryCollection Typesに準拠していることがわかりますね。Collection Typesに準拠したクラスは複数の明示された型のキーや値を格納することができ、それ以外の方を格納することは出来ません。つまり、キーや値の型を取得する際は想定された型を受け取ることが保証できます。


要素の重複と順序

型によって要素の順序や重複した要素を格納できるかが異なります。


要素の順序
要素の重複

Array
要素を入れた順

Set
順不同
×

Dictionary
順不同
key × value


変数定義

// Array

var array: [Int] = []

//Dictionary
var dictionary: [Int: String] = [:]

// Array

var array = [Int]()
var arrayWithValues = ["value1", "value2"]

// Set
var set = Set<Character>()
var setWithValues: Set = ["value1", "value2", "value3"]

//Dictionary
var dictionary = [Int: String]()
var dictionaryWithKeyValue = ["key1": "value1", "key2": "value2"]

//どうしても変数である必要がある場合以外はletで宣言する
let constArray = ["value1", "value2"]


  • 以下の定義の仕方は非推奨


var array: [Int] = [Int]()
var array = Array<Int>()
var dictionary: [Int: String] = [Int: String]()
var dictionary = Dictionary<Int, String>()


基本的な使い方

以下の書き方はCollection Typesを参考にしています。


Array

var someInts = [Int]()

//[]
someInts.append(3)
//[3]
someInts += [2, 5]
//[3, 2, 5]
someInts = []
//[]

var threeDouble = [Double](count: 3, repeatedValue: 0.0)
// [0, 0, 0]
var anotherThreeDoubles = [Double](count: 3, repeatedValue: 2.3)
//[2.3, 2.3, 2.3]
var sixDouble = threeDouble + anotherThreeDoubles
//[0, 0, 0, 2.3, 2.3, 2.3]

//要素と一緒に初期化
var shoppingList = ["Eggs", "Milk"]
// ["Eggs", "Milk"]
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
//["Eggs", "Milk", "Chocolate Spread", "Cheese", "Butter"]
shoppingList.count
//5
shoppingList[0] = "two Eggs"
//["two Eggs", "Milk", "Chocolate Spread", "Cheese", "Butter"]
shoppingList[1...2] = ["Bananas", "Apples"]
//["two Eggs", "Bananas", "Apples", "Cheese", "Butter"]
shoppingList.insert("Maple Syrup", atIndex: 0)
//["Maple Syrup", "two Eggs", "Bananas", "Apples", "Cheese", "Butter"]

let mapleSyrup = shoppingList.removeAtIndex(0)
print(mapleSyrup)
//"Maple Syrup"
print(shoppingList)
//["two Eggs", "Bananas", "Apples", "Cheese", "Butter"]

let apples = shoppingList.removeLast()
print(apples)
//"Butter"
print(mapleSyrup)
//["two Eggs", "Bananas", "Apples", "Cheese"]

if shoppingList.isEmpty {
print("empty")
} else {
print("contain value")
}
//contain value


Set

//空のSet

var letters = Set<Character>()
//[]
letters.insert("a")
//{"a"}
letters = []
//[]

//要素と一緒に初期化
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
//{"Rock", "Classical", "Hip hop"}
favoriteGenres.count
//3
favoriteGenres.insert("Jazz")
//{"Rock", "Classical", "Jazz", "Hip hop"}
//Jazzは最後に追加されてないことに注意

if let removedGenre = favoriteGenres.remove("Rock") {
print("removed Rock")
}
//"removed Rock"

if favoriteGenres.contains("Hip hop") {
print("contain Hip hop")
}
//"contain Hip hop"

if favoriteGenres.isEmpty {
print("empty")
} else {
print("contain value")
}
// "contain value"

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

oddDigits.union(evenDigits).sort()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersect(evenDigits).sort()
// []
oddDigits.subtract(singleDigitPrimeNumbers).sort()
// [1, 9]
oddDigits.exclusiveOr(singleDigitPrimeNumbers).sort()
// [1, 2, 9]



  • a.union(b) : 重複を除くaとbに含まれるすべての要素


  • a.intersect(b) : aとbので重複している要素


  • a.subtract(b) : aからaとbで重複している要素を除いた要素


  • a.exclusiveOr(b): aとbで重複してない要素


Dictionary

var namesOfIntegers = [Int: String]()

//[:]
namesOfIntegers[16] = "sixteen"
//[16: "sixteen"]
namesOfIntegers = [:]
//[:]

//要素と一緒に初期化
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
//["DUB": "Dublin", "YYZ": "Toronto Pearson"]
airports.count
//2

airports["LHR"] = "London"
//["DUB": "Dublin", "LHR": "London", "YYZ": "Toronto Pearson"]
airports["LHR"] = "London Heathrow"
//["DUB": "Dublin", "LHR": "London Heathrow", "YYZ": "Toronto Pearson"]

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
print(oldValue)
//Dublin
}
print(airports)
//"["DUB": "Dublin Airport", "LHR": "London Heathrow", "YYZ": "Toronto Pearson"]

if let airportName = airports["DUB"] {
print(airportName)
//Dublin Airport
}
airports["APL"] = "Apple International"
//["APL": "Apple International", "YYZ": "Toronto Pearson", "DUB": "Dublin Airport", "LHR": "London Heathrow"]
airports["APL"] = nil
//["YYZ": "Toronto Pearson", "DUB": "Dublin Airport", "LHR": "London Heathrow"]
//APLのキーごと要素がなくなる

if let removedValue = airports.removeValueForKey("DUB") {
print(removedValue)
//Dublin Airport
print(airports)
//["YYZ": "Toronto Pearson", "LHR": "London Heathrow"]
}

if airports.isEmpty {
print("empty")
} else {
print("contain elements")
}
//contain elements

let airportCodes = [String](airports.keys)
//["YYZ", "LHR"]
let airportNames = [String](airports.values)
//["Toronto Pearson", "London Heathrow"]


For-In Loops

要素が複数格納されているCollection Typesに準拠する型はloop処理によって要素を参照することができます。

//Array

let array = ["Qiita", "Swift", "Objective-C", "iOS"]

for value in array {
print(value)
}
//Qiita
//Swift
//Objective-C
//iOS

//enumerate()は配列のindexと値のタプルを返す
for (index, value) in array.enumerate() {
print("index: \(index) value: \(value)")
}
//index: 0 value: Qiita
//index: 1 value: Swift
//index: 2 value: Objective-C
//index: 3 value: iOS

//Dictionary
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
// ants have 6 legs
// cats have 4 legs
// spiders have 8 legs


高階関数

Collection Typesに準拠するArray, SetDictionaryなどはmapなどの高階関数が利用できます。高階関数やClosureについてはSwiftらしいコーディングを学ぶ 「コレクションに用いる高階関数とClosure」の記事にまとめてあります。


参考