トラック
/
Crystal
Crystal
/
演習
/
言語リスト
言語リスト

言語リスト

学習演習

はじめに

配列は、特定の型の要素のコレクションを格納するミュータブルなデータ構造です。 配列はインデックス可能なデータ構造です。 配列がミュータブルであるということは、配列を変更するメソッドを配列に対して呼び出すと、その配列が変更されるということです。 つまり、新しい配列を作るのではなく、既存の配列を変更します。

配列を作るには、配列リテラルの記法([])を使い、その中に配列の要素をカンマで区切って指定します。

[1, 2, 3] # => [1, 2, 3]

Crystalは要素から配列の型を推論します。

[1, 2, 3].class # => Array(Int32)

複数の型の配列

先ほど配列は特定の型の要素のコレクションだと説明しましたが、共用型を使えば複数の型を持つ配列を作ることができます。 これにより、配列は共用型で指定されたいずれかの型の要素を含むことができます。 Crystalは要素から配列の型を推論します。

[1, "2", 3.0] # => [1, "2", 3.0]

[1, "2", 3.0].class # => Array(Int32 | Float64 | String)

多次元配列

多次元配列とは、配列の配列です。 つまり、配列の各要素がそれ自体配列です。 これは、データを表形式で保存したいときに便利です。 多次元配列を定義するには、配列の配列のリテラルを書くか、Array.newコンストラクターを使います。

[[1, 2], [3, 4]]                    # => [[1, 2], [3, 4]]
numbers = Array(Array(Int32)).new() # => []
numbers << [1, 2]                   # => [[1, 2]]

配列に要素を追加する

配列に要素を追加するには、<<(追加)演算子を使います。

[1, 2, 3] << 4 # => [1, 2, 3, 4]

追加したい要素の型は、配列の型と同じでなければなりません。そうでない場合はエラーが発生します。

numbers : Array(Int32 | Float64) = [1, 2, 3]
numbers << 4.0
numbers # => [1, 2, 3, 4.0]

numbers << "5" # => Error: no overload matches 'Array(Int32 | Float64)#<<' with type String

配列のサイズ

Stringと同様に、sizeメソッドを使うと配列のサイズを取得できます。

[1, 2, 3].size # => 3

空の配列

空の配列を作るとき、コンパイラーは配列の型を推論できません。 そのため、配列の型を指定する必要があります。 これには、ofキーワードを使って配列の型を指定するか、配列の初期化構文であるArray(T).newを使います。

[] of (Int32 | Float64 | String)    # => []
Array(Int32 | Float64 | String).new # => []

要素へのアクセス

Stringと同様に、[](インデックス)演算子を使って、アクセスしたい要素のインデックスを渡すと、配列の要素にアクセスできます。 インデックスが範囲外の場合、IndexErrorが発生します。

[1, 2, 3][0] # => 1

[1, 2, 3][3] # => Index out of bounds (IndexError)

範囲を使って要素にアクセスすることもできます。

[1, 2, 3][0..1] # => [1, 2]

範囲から配列を作成する

範囲から配列を作成するには、to_aメソッドを使います。 これは、数値の配列を作りたいときに便利です。

(1..3).to_a # => [1, 2, 3]

文字列から配列を作成する

文字列から配列を作成するには、splitメソッドを使います。 これにより、区切り文字を使って文字列を文字列の配列に分割できます。

"1,2,3".split(",") # => ["1", "2", "3"]

charsメソッドを使って文字列から文字の配列を取得することもできます。

"123".chars # => ['1', '2', '3']

CharまたはStringの配列をStringに変換するには、区切り文字を引数に取るjoinメソッドを使います。

['1', '2', '3'].join(".") # => "1.2.3"

配列から要素を削除する

配列の末尾から要素を削除したいときは、popメソッドを使います。このメソッドは、配列の末尾から削除する要素の数を指定する省略可能な引数を取ります。 このメソッドは削除された要素を返します。 配列が空の場合、IndexErrorが発生します。

numbers = [1, 2, 3]
numbers.pop # => 3
numbers     # => [1, 2]

empty_numbers = [] of Int32
empty_numbers.pop # => Index out of bounds (IndexError)

配列から特定のインデックスの要素を削除したいときは、delete_atメソッドを使います。このメソッドは、削除する要素のインデックスを引数に取ります。 配列が空の場合、IndexErrorが発生します。

numbers = [1, 2, 3]
numbers.delete_at(1) # => 2
numbers              # => [1, 3]

empty_numbers = [] of Int32
empty_numbers.delete_at(0) # => Index out of bounds (IndexError)

配列の値を変更する

配列の特定のインデックスの要素を変更したいときは、[]=(インデックス代入)演算子を使います。この演算子は、変更する要素のインデックスと新しい値を引数に取ります。 インデックスが範囲外の場合、IndexErrorが発生します。

numbers = [1, 2, 3]
numbers[1] = 4
numbers # => [1, 4, 3]

numbers[3] = 5 # => Index out of bounds (IndexError)

説明

この演習では、プログラミング言語の配列を操作するいくつかのメソッドを実装します。

1. 空の言語の配列を返すメソッドを定義する

引数を取らず、型Array(String)の空の配列を返すLanguageList.listメソッドを定義します。

LanguageList.list()
# => []

2. 配列に言語を追加するメソッドを定義する

2つの引数(_言語の配列_と、_言語_の文字列リテラル)を取るLanguageList.addメソッドを定義します。 このメソッドは、新しい言語を配列の末尾に追加した配列を返します。

language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]

3. 配列から言語を取り除くメソッドを定義する

1つの引数(言語の配列)を取るLanguageList.removeメソッドを定義します。 このメソッドは、最後の要素を取り除いた配列を返します。 配列には常に少なくとも1つの要素があると仮定します。

language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
language_list = LanguageList.remove(language_list)
# => ["Crystal"]

4. 配列のn番目の要素を返すメソッドを定義する

2つの引数(_言語の配列_とインデックス)を取るLanguageList.at関数を定義します。 このメソッドは、配列のn番目のインデックスにある言語を返します。 インデックスの位置には常に言語があると仮定します。

language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
LanguageList.at(language_list, 1)
# => "Ruby"

5. 言語の文字列を解析するメソッドを定義する

1つの引数(カンマで区切られた言語の文字列リテラル)を取るLanguageList.parseメソッドを定義します。 このメソッドは、言語の配列を返します。

LanguageList.parse("Crystal, Ruby")
# => ["Crystal", "Ruby"]
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Crystal Exercism

言語リストを始める準備はできましたか?

Exercismに登録すれば、26個のコンセプト142個の演習、そして本物の人間によるメンタリングとともに、Crystalを学んでマスターできます。すべて無料です。