배열은 특정 타입의 원소 모음을 저장하는 가변 자료 구조예요. 배열은 인덱스로 접근할 수 있는 자료 구조예요. 배열이 가변이라는 것은, 배열을 수정하는 메서드를 배열에 호출하면 그 배열이 수정된다는 뜻이에요. 즉, 새로운 배열을 만드는 것이 아니라 기존 배열을 수정해요.
배열을 만들려면 배열 리터럴 표기법([])을 사용하고, 그 안에 배열의 원소들을 쉼표로 구분해서 적어요.
[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)
이 연습 문제에서는 프로그래밍 언어 배열을 다루는 몇 가지 메서드를 구현해요.
인자를 받지 않고 Array(String) 타입의 빈 배열을 반환하는 LanguageList.list 메서드를 정의해요.
LanguageList.list()
# => []
두 개의 인자(_언어 배열_과 _언어_를 나타내는 문자열 리터럴)를 받는 LanguageList.add 메서드를 정의해요.
이 메서드는 배열 끝에 새 언어를 추가한 배열을 반환해야 해요.
language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
인자 하나(언어 배열)를 받는 LanguageList.remove 메서드를 정의해요.
이 메서드는 마지막 원소를 제거한 배열을 반환해야 해요.
배열에는 항상 원소가 최소한 하나는 있다고 가정해요.
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"]
두 개의 인자(_언어 배열_과 인덱스)를 받는 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"
인자 하나(쉼표로 구분된 언어들의 문자열 리터럴)를 받는 LanguageList.parse 메서드를 정의해요.
이 메서드는 언어 배열을 반환해야 해요.
LanguageList.parse("Crystal, Ruby")
# => ["Crystal", "Ruby"]
Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.