配列は、Swiftの3つの主要なコレクション型の1つです。 配列は、要素を順番に並べたリストです。 配列にはどのような型の要素でも格納できますが、1つの配列の中の要素はすべて同じ型でなければなりません。 配列は、変数に代入すると可変になり、配列を作成したあとで要素を追加・削除・変更できます。 定数に代入すると不変になり、中身を変更することはできません。
配列リテラルは、角括弧([...])で囲んだ、カンマ区切りの要素のリストとして書きます。
Swiftは、リテラルの中の要素から配列の型を推論できます。
let evenInts = [2, 4, 6, 8, 10, 12]
var oddInts = [1, 3, 5, 7, 9, 11, 13]
let greetings = ["Hello!", "Hi!", "¡Hola!"]
型を明示的に指定することもできます。
配列の型は2通りの方法で書けます。Array<T>か、省略記法の[T]です。ここでTは、配列に格納される値の型を表します。
let evenInts: Array<Int> = [2, 4, 6, 8, 10, 12]
var oddInts: [Int] = [1, 3, 5, 7, 9, 11, 13]
let greetings: [String] = ["Hello!", "Hi!", "¡Hola!"]
countプロパティを使うと、配列の要素数を調べられます。
evenInts.count
// returns 6
空の配列を作るには、型を指定する必要があります。 これには、配列のイニシャライザ構文か、明示的な型注釈を使います。
let emptyArray = [Int]()
let emptyArray2 = Array<Int>()
let emptyArray3: [Int] = []
配列を入れ子にすると、多次元配列を作れます。
入れ子になった配列の型を明示的に指定するときは、[[Int]]やArray<Array<Int>>のように、要素の型を入れ子の角括弧で囲みます。
let multiDimArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let multiDimArray2: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
append(_:)メソッドを使うと、可変の配列の末尾に要素を追加できます。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.append(15)
// oddInts is now [1, 3, 5, 7, 9, 11, 13, 15]
insert(_:at:)メソッドを使うと、指定したインデックスに要素を挿入できます。
このメソッドは2つの引数を取ります。挿入する要素と、挿入する位置のインデックスです。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.insert(0, at: 0)
// oddInts is now [0, 1, 3, 5, 7, 9, 11, 13]
+演算子を使うと、2つの配列を1つの配列にまとめられます。
+演算子は新しい配列を作って返します。元の配列は変更しません。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
let combined = oddInts + [15, 17, 19]
// combined is [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
print(oddInts)
// prints [1, 3, 5, 7, 9, 11, 13]
配列名のあとに角括弧([])を書き、その中にインデックスを入れると、配列の個々の要素にアクセスできます。
配列のインデックスは0から始まるInt値で、最初の要素は0です。
有効な範囲外のインデックスにアクセスすると、実行時エラーが発生し、プログラムがクラッシュします。
let evenInts = [2, 4, 6, 8, 10, 12]
let oddInts = [1, 3, 5, 7, 9, 11, 13]
evenInts[2]
// returns 6
oddInts[7]
// Fatal error: Index out of range
可変の配列では、特定のインデックスに新しい値を代入すると、その要素を変更できます。 要素を読み取るときと同様、有効な範囲外のインデックスを使うと実行時エラーが発生します。
var evenInts = [2, 4, 6, 8, 10, 12]
evenInts[2] = 0
// evenInts is now [2, 4, 0, 8, 10, 12]
joined(separator:)メソッドを使うと、文字列の配列を1つの文字列に連結できます。このメソッドは区切り文字の文字列を取ります。
let evenInts = ["2", "4", "6", "8", "10", "12"]
let evenIntsString = evenInts.joined(separator: ", ")
// returns "2, 4, 6, 8, 10, 12"
split(separator:)メソッドに区切り文字を渡すと、文字列を部分文字列の配列に分割できます。
let evenIntsString = "2, 4, 6, 8, 10, 12"
let evenInts = evenIntsString.split(separator: ",")
// returns ["2", " 4", " 6", " 8", " 10", " 12"]
remove(at:)メソッドを使うと、指定したインデックスの要素を削除できます。
インデックスは配列の有効な範囲内でなければなりません。そうでない場合は実行時エラーが発生します。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.remove(at: 3)
// oddInts is now [1, 3, 5, 9, 11, 13]
配列の最後の要素を削除するには、removeLast()メソッドを使います。
空の配列に対してremoveLast()を呼び出すと、実行時エラーが発生します。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.removeLast()
// oddInts is now [1, 3, 5, 7, 9, 11]
駆け出しのマジシャンであるElyseは、基本をいくつか練習する必要があります。彼女は、操ってみたいカードの山を持っています。
少しでも簡単にするために、彼女は1から10までのカードだけを使います。そうすれば、カードの山を数値の配列で表せるからです。あるカードの位置は、配列のインデックスに対応します。つまり、位置0が1枚目のカード、位置1が2枚目のカードを指します。
すべての関数は、カードの配列を更新してから、更新した配列を返すようにします。これはビルダーパターンと呼ばれる一般的な作り方で、関数をきれいにつなげて書けるようになります。
カードを1枚選ぶには、与えられた山のインデックスpositionにあるカードを返します。
関数getCard(at:from:)を実装します。この関数は2つの引数を取ります。atは山の中でのカードの位置、fromはカードの山です。この関数は、与えられた山から位置indexにあるカードを返します。
let index = 2
getCard(at: index, from: [1, 2, 4, 1])
// returns 4
手品のような手さばきで、インデックスpositionにあるカードを、用意された新しいカードと入れ替えます。
関数setCard(at:in:to)を実装します。この関数は3つの引数を取ります。atは山の中でのカードの位置、inはカードの山、toは位置indexのカードと入れ替える新しいカードです。この関数は、位置indexのカードを新しいカードで置き換えた山のコピーを返します。与えられたindexが山の中の有効なインデックスでない場合は、元の山をそのまま返します。
let index = 2
let newCard = 6
setCard(at: index, in: [1, 2, 4, 1], to: newCard)
// returns [1, 2, 6, 1]
山の一番上に新しいカードを挿入して、カードを出現させます。
関数insert(_:atTopOf:)を実装します。この関数は2つの引数を取ります。挿入する新しいカードと、カードの山です。この関数は、用意された新しいカードを山の一番上に加えた山のコピーを返します。
let newCard = 8
insert(newCard, atTopOf: [5, 9, 7, 1])
// returns [5, 9, 7, 1, 8]
与えられたpositionにあるカードを山から取り除いて、カードを消します。
関数removeCard(at:from:)を実装します。この関数は2つの引数を取ります。atは山の中でのカードの位置、fromはカードの山です。この関数は、位置indexのカードを取り除いた山のコピーを返します。与えられたindexが山の中の有効なインデックスでない場合は、元の山をそのまま返します。
let index = 2
removeCard(at: index, from: [3, 2, 6, 4, 8])
// returns [3, 2, 4, 8]
与えられたpositionに新しいカードを挿入して、カードを出現させます。
関数insert(_:at:from:)を実装します。この関数は3つの引数を取ります。挿入する新しいカード、新しいカードを挿入する位置、カードの山です。この関数は、用意された新しいカードを与えられた位置に加えた山のコピーを返します。与えられたindexが山の中の有効なインデックスでない場合は、元の山をそのまま返します。
let newCard = 8
insert(newCard, at: 2, from: [5, 9, 7, 1])
// returns [5, 9, 8, 7, 1]
山の枚数がstackSizeと同じかどうかを確認します。
関数checkSizeOfStack(_:_:)を実装します。この関数は2つの引数を取ります。stackはカードの山、stackSizeは山の枚数です。この関数は、山の枚数がstackSizeと同じであればtrueを、そうでなければfalseを返します。
let stackSize = 4
checkSizeOfStack([3, 2, 6, 4, 8], stackSize)
// returns false