Ruby에서 배열 메서드를 사용하는 방법
소개
문자열, 한 데이터 배열을 다른 배열로 변환하고 배열을 단일 값으로 롤업합니다.
이 튜토리얼에서는 Ruby가 배열에 저장된 데이터 작업을 위해 제공하는 가장 실용적인 방법 중 일부를 탐색합니다.
이 자습서를 진행하면서 느낌표(!
)로 끝나는 몇 가지 메서드를 볼 수 있습니다. 이러한 메서드에는 원래 값을 변경하거나 예외를 발생시키는 것과 같은 부작용이 있는 경우가 많습니다. 이 자습서에서 사용하게 될 많은 메서드에는 이 접미사가 있는 관련 메서드가 있습니다.
또한 물음표(?
)로 끝나는 메소드를 보게 될 것입니다. 이러한 메서드는 부울 값을 반환합니다.
이는 Ruby 전체에서 사용되는 명명 규칙입니다. 프로그램 수준에서 시행되는 것이 아닙니다. 방법에서 기대할 수 있는 것을 식별하는 또 다른 방법입니다.
요소에 액세스하는 여러 가지 방법을 살펴봄으로써 배열 메서드 탐색을 시작하겠습니다.
요소에 접근하기
Ruby에서 배열로 작업하는 방법 튜토리얼을 이미 따랐다면 다음과 같이 0부터 시작하는 인덱스를 사용하여 개별 요소에 액세스할 수 있다는 것을 알고 있습니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[0] # "Tiger"
sharks[1] # "Great White"
sharks[-1] # "Angel"
또한 first
및 last
메서드를 사용하여 배열의 첫 번째 요소와 마지막 요소를 가져올 수 있다는 것을 기억할 것입니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.first # "Tiger"
sharks.last # "Angel"
마지막으로 존재하지 않는 요소에 액세스하면 nil
이 표시됩니다. 하지만 대신 오류가 발생하려면 fetch
메서드를 사용하세요.
sharks.fetch(42)
OutputIndexError: index 42 outside of array bounds: -4...4
오류를 발생시키는 대신 고유한 기본값을 지정하려는 경우에도 그렇게 할 수 있습니다.
sharks.fetch(42, "Nope") # "Nope"
이제 배열에서 하나 이상의 요소를 가져오는 방법을 살펴보겠습니다.
여러 요소 검색
단일 요소 대신 배열에서 값의 하위 집합을 가져오려는 경우가 있습니다.
시작 인덱스와 원하는 요소 수를 지정하면 해당 값을 포함하는 새 배열을 얻게 됩니다. 예를 들어 다음과 같이 sharks
배열에서 두 개의 중간 항목을 가져올 수 있습니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[1,2] # ["Great White", "Hammerhead"]
\Great White\
인 인덱스 1
에서 시작하고 원하는 2
요소를 지정하여 <를 포함하는 새 배열을 얻습니다. code>\그레이트 화이트\ 및 \해머헤드\
.
slice
메서드를 사용하여 동일한 작업을 수행할 수 있습니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.slice(1,2) # ["Great White", "Hammerhead"]
slice
메서드는 원래 배열을 변경하지 않고 새 배열도 반환합니다. 그러나 slice!
방법을 사용하면 원래 배열도 변경됩니다.
take
메소드를 사용하면 배열 시작 부분에서 지정된 수의 항목을 가져올 수 있습니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.take(2) # ["Tiger", "Great White"]
특정 값 대신 배열에서 임의의 값을 가져오려는 경우가 있습니다. 방법을 살펴보겠습니다.
배열에서 임의 항목 가져오기
우연의 게임을 진행 중일 수도 있고 대회 우승자를 선택하는 프로그램을 작성 중일 수도 있습니다. 그런 종류의 것들은 일종의 임의의 값을 필요로 합니다. 일반적인 솔루션은 가능한 선택 항목을 배열에 넣고 임의 인덱스를 선택하는 것입니다.
배열에서 임의의 요소를 가져오려면 0
과 배열의 마지막 인덱스 사이에 임의의 인덱스를 생성하고 이를 인덱스로 사용하여 값을 검색할 수 있지만 더 쉬운 방법이 있습니다. code>sample 메서드는 배열에서 임의의 항목을 가져옵니다.
이를 사용하여 재고 답변 배열에서 무작위 답변을 가져와 Magic 8-Ball 게임의 기본 버전을 만들어 보겠습니다.
answers = ["Yes", "No", "Maybe", "Ask again later"]
print answers.sample
OutputMaybe
sample
메서드는 임의 항목의 배열을 반환하는 인수도 허용하므로 둘 이상의 임의 항목이 필요한 경우 원하는 수를 제공하십시오.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sample = sharks.sample(2)
print sample
Output["Whale", "Great White"]
다음으로 배열에서 특정 요소를 찾는 방법을 살펴보겠습니다.
요소 찾기 및 필터링
배열에서 특정 요소를 찾을 때 일반적으로 원하는 것을 찾을 때까지 해당 요소를 반복합니다. 그러나 Ruby 배열은 배열 검색 프로세스를 단순화하도록 특별히 설계된 몇 가지 방법을 제공합니다.
요소가 존재하는지 확인하려는 경우 지정된 데이터가 배열의 요소인 경우 true
를 반환하는 include?
메서드를 사용할 수 있습니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger" # true
["a", "b", "c"].include? 2 # false
그러나 include?
는 정확히 일치해야 하므로 부분 단어를 찾을 수 없습니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
sharks.include? "Tiger" # true
sharks.include? "tiger" # false
sharks.include? "ti" # false
find
메소드는 지정한 조건과 일치하는 배열의 첫 번째 요소를 찾아 반환합니다.
예를 들어 문자 a
를 포함하는 sharks
배열의 첫 번째 항목을 식별하려면 each
메서드를 사용하여 각 항목과 다음과 같이 첫 번째 것을 찾으면 반복을 중지하십시오.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = nil
sharks.each do |shark|
if sharks.include? "a"
result = shark
break
end
end
또는 find
메서드를 사용하여 동일한 작업을 수행할 수 있습니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.find {|item| item.include?("a")}
print result
OutputHammerhead
find
는 배열의 각 요소에 대해 제공한 블록을 실행합니다. 블록의 마지막 표현식이 true
로 평가되면 find
메서드는 값을 반환하고 반복을 중지합니다. 모든 요소를 반복한 후에도 아무 것도 찾지 못하면 nil
을 반환합니다.
select
메서드는 비슷한 방식으로 작동하지만 단일 값을 반환하고 중지하는 대신 조건과 일치하는 모든 요소를 포함하는 새 배열을 구성합니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.select {|item| item.include?("a")}
print results
Output["Hammerhead", "Great White", "Whale"]
reject
메서드는 조건과 일치하지 않는 요소를 포함하는 새 배열을 반환합니다. 원하지 않는 요소를 제거하는 필터라고 생각하시면 됩니다. 다음은 문자 a
를 포함하는 모든 항목을 거부하는 예입니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
results = sharks.reject {|item| item.include?("a")}
print results
Output["Tiger"]
select
및 reject
는 모두 원래 배열을 변경하지 않고 새 배열을 반환합니다. 그러나 select!
및 reject!
메소드를 사용하면 원래 배열이 수정됩니다.
find_all
메서드는 select
의 별칭이지만 find_all!
메서드는 없습니다.
다음으로 배열의 값을 정렬하는 방법을 살펴보겠습니다.
배열 정렬
데이터 정렬은 일반적인 관행입니다. 이름 목록을 알파벳순으로 정렬하거나 숫자를 작은 것부터 큰 것까지 정렬해야 할 수도 있습니다.
Ruby 배열에는 배열 요소의 순서를 뒤집을 수 있는 reverse
메서드가 있습니다. 이미 정리된 데이터 목록이 있는 경우 reverse
는 요소를 뒤집는 빠른 방법입니다.
sharks = ["Angel", "Great White", "Hammerhead", "Tiger"]
reversed_sharks = sharks.reverse
print reversed_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]
reverse
메서드는 새 배열을 반환하고 원본을 수정하지 않습니다. 대신 원래 배열을 변경하려면 reverse!
방법을 사용하십시오.
그러나 배열을 뒤집는 것이 항상 데이터를 정렬하는 가장 효율적이거나 실용적인 방법은 아닙니다. sort
메서드를 사용하여 원하는 방식으로 배열의 요소를 정렬합니다.
단순한 문자열 또는 숫자 배열의 경우 sort
방법이 효율적이며 원하는 결과를 제공합니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort
print sorted_sharks
Output["Angel", "Great White", "Hammerhead", "Tiger"]
그러나 다른 방식으로 정렬하고 싶다면 sort
메소드에 그 방법을 알려주고 싶을 것입니다. 정렬
메서드는 배열의 요소에 대한 액세스를 제공하는 Ruby 블록을 사용하므로 요소를 비교할 수 있습니다.
비교하려면 종종 우주선 연산자라고 하는 비교 연산자(<=>
)를 사용합니다. 이 연산자는 두 Ruby 객체를 비교하여 왼쪽 객체가 더 작으면 -1
을, 객체가 같으면 0
을, 1
을 반환합니다. 왼쪽에 있는 물체가 더 큰 경우.
1 <=> 2 # -1
2 <=> 2 # 0
2 <=> 1 # 1
Ruby의 정렬
메서드는 -1
, 0
또는 1
을 반환해야 하는 블록을 받아들입니다. 배열의 값을 정렬합니다.
다음은 오름차순으로 정렬하기 위해 배열의 항목을 명시적으로 비교하는 예입니다.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| a <=> b }
print sorted_sharks
a
및 b
변수는 비교되는 배열의 개별 요소를 나타냅니다. 결과는 다음과 같습니다.
Output["Angel", "Great White", "Hammerhead", "Tiger"]
상어를 역순으로 정렬하려면 비교 대상을 뒤집으십시오.
sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sorted_sharks = sharks.sort{|a,b| b <=> a }
print sorted_sharks
Output["Tiger", "Hammerhead", "Great White", "Angel"]
정렬
방법은 정수, 실수 및 문자열과 같은 간단한 데이터 유형을 포함하는 배열에 적합합니다. 그러나 배열에 더 복잡한 개체가 포함되어 있으면 조금 더 많은 작업을 수행해야 합니다.
다음은 해시 배열이며 각 해시는 상어를 나타냅니다.
sharks = [
{name: "Hammerhead"},
{name: "Great white"},
{name: "Angel"}
]
sort
로 이것을 정렬하는 것은 쉽지 않습니다. 배열에서 sort
를 호출하면 실패합니다.
sharks.sort
OutputArgumentError: comparison of Hash with Hash failed
비교를 하기 위해서는 비교하고자 하는 것을 sort
에 알려줘야 합니다. 따라서 해시에서 :name
키의 값을 비교합니다.
sorted_sharks.sort{|a, b| a[:name] <=> b[:name]}
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
더 복잡한 구조로 작업할 때 보다 효율적인 정렬 알고리즘을 사용하는 sort_by
메서드를 대신 살펴보는 것이 좋습니다. sort_by
는 배열의 현재 요소에 대한 참조인 하나의 인수만 필요한 블록을 사용합니다.
sharks = [
{name: "Hammerhead"},
{name: "Great white"},
{name: "Angel"}
]
sorted_sharks = sharks.sort_by{|shark| shark[:name] }
print sorted_sharks
Output[{:name=>"Angel"}, {:name=>"Great white"}, {:name=>"Hammerhead"}]
sort_by
메서드는 특정 키 값을 기준으로 개체를 비교하는 데 가장 적합한 정렬 알고리즘인 Schwartzian 변환을 구현합니다. 따라서 개체 컬렉션을 비교할 때마다 sort_by
를 사용하는 것이 더 효율적임을 알게 될 것입니다.
sort
및 sort_by
는 원래 배열을 그대로 두고 새 배열을 반환합니다. 원래 배열을 수정하려면 sort!
및 sort_by!
를 대신 사용하세요.
값을 정렬하는 것 외에도 중복 항목을 제거할 수도 있습니다.
중복 요소 제거
가끔 중복이 있는 데이터 목록을 얻을 수 있습니다. 배열을 반복하고 중복 항목을 걸러낼 수 있지만 Ruby의 uniq
메서드를 사용하면 훨씬 쉬워집니다. uniq
메서드는 모든 중복 값이 제거된 새 배열을 반환합니다.
[1,2,3,4,1,5,3].uniq # [1,2,3,4,5]
경우에 따라 두 데이터 집합을 병합하면 중복 데이터가 생성됩니다. 다음 두 가지 상어 배열을 살펴보십시오.
sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]
함께 추가하면 중복 항목이 생성됩니다.
sharks + new_sharks
# ["Tiger", "Great White", "Tiger", "Hammerhead"]
uniq
를 사용하여 중복을 제거할 수 있지만 중복을 완전히 도입하지 않는 것이 좋습니다. 배열을 함께 추가하는 대신 배열을 병합하는 파이프 연산자|
를 사용하십시오.
sharks | new_sharks
# ["Tiger", "Great White", "Hammerhead"]
Ruby 배열은 빼기도 지원합니다. 즉, sharks
에서 new_sharks
를 빼서 새 값만 얻을 수 있습니다.
sharks = ["Tiger", "Great White"]
new_sharks = ["Tiger", "Hammerhead"]
sharks - new_sharks # ["Great White"]
다음으로 각 요소의 값을 조작하는 방법을 살펴보겠습니다.
데이터 변환
map
메서드와 해당 별칭인 collect
는 배열의 내용을 변환할 수 있습니다. 즉, 배열의 각 요소에 대해 작업을 수행할 수 있습니다.
예를 들어 map
을 사용하여 배열의 각 항목에 대해 산술 연산을 수행하고 새 값을 포함하는 새 배열을 만들 수 있습니다.
numbers = [2,4,6,8]
# square each number
squared_numbers = numbers.map {|number| number * number}
print squared_numbers
squared_numbers
변수는 제곱된 원래 숫자의 배열입니다.
[4, 16, 36, 64]
map
은 배열을 HTML 드롭다운 목록의 요소로 변환하기 위해 웹 애플리케이션에서 자주 사용됩니다. 다음은 매우 단순화된 버전입니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
options = sharks.map {|shark| "<option>#{shark}</option>"}
print options
options
배열에는 이제 각 상어가 HTML 태그로 래핑되어 있습니다.
["<option>Hammerhead</option>", "<option>Great White</option>", "<option>Tiger</option>", "<option>Whale</option>"]
map
은 원래 배열을 수정하지 않고 새 배열을 반환합니다. map!
을 사용하면 기존 배열이 수정됩니다. 그리고 map
에는 collect
라는 별칭이 있다는 것을 기억하세요. 일관성을 유지하고 코드에서 둘 중 하나를 사용해야 합니다.
map
은 새 배열을 반환하므로 배열을 변환하고 추가로 조작하거나 문자열로 변환할 수도 있습니다. 다음에 살펴보겠습니다.
배열을 문자열로 변환
Ruby의 모든 객체에는 객체를 문자열로 변환하는 to_s
메서드가 있습니다. 이것이 print
문이 사용하는 것입니다. 주어진 상어
배열:
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
to_s
메서드를 호출하면 다음 문자열이 생성됩니다.
"[\"Hammerhead\", \"Great White\", \"Tiger\", \"Whale\"]"
디버깅에는 좋지만 실제 프로그램에서는 그리 유용하지 않습니다.
join
메서드는 배열을 문자열로 변환하지만 요소를 결합하는 방법을 훨씬 더 많이 제어할 수 있습니다. join
메서드는 구분 기호로 사용할 문자를 지정하는 인수를 사용합니다. 상어 배열을 공백으로 구분된 일련의 상어 이름으로 변환하려면 다음과 같이 합니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(" ")
print result
OutputHammerhead Great White Tiger Whale
각 상어 이름을 쉼표 및 공백으로 구분하려면 쉼표와 공백을 구분 기호로 사용하십시오.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(", ")
print result
OutputHammerhead, Great White, Tiger, Whale
join
메서드에 대한 인수를 지정하지 않으면 여전히 문자열을 얻지만 구분 기호는 없습니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join
print result
OutputHammerheadGreat WhiteTigerWhale
map
과 함께 join
을 사용하면 데이터 배열을 출력으로 빠르게 변환할 수 있습니다. map
을 사용하여 데이터의 각 요소를 변환한 다음 join
을 사용하여 전체를 인쇄할 수 있는 문자열로 변환합니다. sharks
배열을 HTML 요소 배열로 변환한 예를 기억하십니까? 동일한 예가 다시 있지만 이번에는 join
을 사용하여 요소 배열을 개행 문자를 구분 기호로 사용하는 문자열로 변환합니다.
sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
options = sharks.map {|shark| "<option>#{shark}</option>"}
output = options.join("\n")
print output
Output<option>Hammerhead</option>
<option>Great White</option>
<option>Tiger</option>
<option>Whale</option>
배열을 문자열로 변환하는 대신 전체 내용을 가져오거나 단일 값을 생성하는 다른 종류의 변환을 수행할 수 있습니다. 그게 다음에 있습니다.
배열을 단일 값으로 줄이기
데이터 집합으로 작업할 때 합계와 같은 단일 값으로 데이터를 롤업해야 할 수 있습니다. 이를 수행할 수 있는 한 가지 방법은 변수와 each
메서드를 사용하는 것입니다.
result = 0
[1, 2, 3].each {|num| result += num}
print result
Output6
대신 reduce
메서드를 사용하여 이 작업을 수행할 수 있습니다. reduce
메서드는 배열을 반복하고 각 요소에 대해 이진 연산을 실행하여 누계를 유지합니다.
reduce
메서드는 결과에 대한 참조와 현재 요소에 대한 참조라는 두 개의 로컬 값이 있는 블록뿐만 아니라 결과에 대한 초기 값을 허용합니다. 블록 내부에서 최종 결과를 계산할 논리를 지정합니다.
배열을 합산하고 싶기 때문에 결과를 0
으로 초기화한 다음 현재 값을 블록의 결과에 추가합니다.
output = [1,2,3].reduce(0) {|result, current| result += current }
print output
Output6
결과를 0
으로 초기화하려는 경우 인수를 생략하고 블록만 전달할 수 있습니다. 이렇게 하면 결과가 배열의 첫 번째 값으로 자동 설정됩니다.
output = [1,2,3].reduce {|result, current| result += current }
print output
Output6
reduce
메소드는 또한 바이너리 메소드 또는 배열의 각 항목에 대해 실행할 다른 객체를 인수로 허용하는 한 객체의 메소드를 지정합니다. reduce
는 결과를 사용하여 단일 값을 생성합니다.
Ruby에서 2 + 2
를 작성하면 실제로 정수 2
에 대해 +
메서드를 호출하는 것입니다.
2.+(2) # 4
Ruby는 약간의 구문 설탕을 사용하므로 2 + 2
로 표현할 수 있습니다.
reduce
메서드를 사용하면 이름을 기호로 전달하여 이진 메서드를 지정할 수 있습니다. 즉, :+
를 reduce
메서드에 전달하여 배열을 합산할 수 있습니다.
output = [1, 2, 3].reduce(:+)
print output
Output6
reduce
를 사용하여 숫자 목록을 더하는 것 이상의 작업을 수행할 수 있습니다. 이를 사용하여 값을 변환할 수 있습니다. reduce
는 배열을 단일 값으로 줄입니다. 그러나 단일 값이 다른 배열이 될 수 없다는 규칙은 없습니다.
정수로 변환해야 하는 값 목록이 있지만 정수로 변환할 수 있는 값만 원한다고 가정해 보겠습니다.
reject
를 사용하여 숫자가 아닌 값을 버린 다음 map
을 사용하여 나머지 값을 정수로 변환할 수 있습니다. 하지만 reduce
를 사용하면 한 번에 모든 작업을 수행할 수 있습니다. 방법은 다음과 같습니다.
빈 배열을 초기화 값으로 사용하십시오. 그런 다음 블록에서 Integer
메서드를 사용하여 현재 값을 정수로 변환합니다. 값을 정수로 변환할 수 없는 경우 Integer
는 예외를 발생시키며, 이를 포착하여 값에 nil
을 할당할 수 있습니다.
그런 다음 값을 가져와 배열에 넣습니다. 단, nil
이 아닌 경우에만 가능합니다.
코드는 다음과 같습니다. 이것을 시도하십시오:
values = ["1", "2", "a", "3"]
integers = values.reduce([]) do |array, current|
val = Integer(current) rescue nil
array.push(val) unless val.nil?
array
end
print integers
Output[1,2,3]
단일 값으로 변환해야 하는 요소 목록이 있을 때마다 reduce
로 해결할 수 있습니다.
결론
이 자습서에서는 배열 작업에 여러 가지 방법을 사용했습니다. 개별 요소를 잡고, 배열을 검색하여 값을 검색하고, 요소를 정렬하고, 데이터를 변환하여 새 배열, 문자열 및 총계를 생성했습니다. 이러한 개념을 적용하여 Ruby로 많은 일반적인 프로그래밍 문제를 해결할 수 있습니다.
Ruby에서 데이터로 작업하는 방법을 계속 탐색하려면 다음 관련 자습서를 살펴보십시오.
- Ruby에서 문자열로 작업하는 방법
- 루비에서 배열로 작업하는 방법
- Ruby의 데이터 유형 이해