웹사이트 검색

Ruby에서 배열 메서드를 사용하는 방법


소개

문자열, 한 데이터 배열을 다른 배열로 변환하고 배열을 단일 값으로 롤업합니다.

이 튜토리얼에서는 Ruby가 배열에 저장된 데이터 작업을 위해 제공하는 가장 실용적인 방법 중 일부를 탐색합니다.

이 자습서를 진행하면서 느낌표(!)로 끝나는 몇 가지 메서드를 볼 수 있습니다. 이러한 메서드에는 원래 값을 변경하거나 예외를 발생시키는 것과 같은 부작용이 있는 경우가 많습니다. 이 자습서에서 사용하게 될 많은 메서드에는 이 접미사가 있는 관련 메서드가 있습니다.

또한 물음표(?)로 끝나는 메소드를 보게 될 것입니다. 이러한 메서드는 부울 값을 반환합니다.

이는 Ruby 전체에서 사용되는 명명 규칙입니다. 프로그램 수준에서 시행되는 것이 아닙니다. 방법에서 기대할 수 있는 것을 식별하는 또 다른 방법입니다.

요소에 액세스하는 여러 가지 방법을 살펴봄으로써 배열 메서드 탐색을 시작하겠습니다.

요소에 접근하기

Ruby에서 배열로 작업하는 방법 튜토리얼을 이미 따랐다면 다음과 같이 0부터 시작하는 인덱스를 사용하여 개별 요소에 액세스할 수 있다는 것을 알고 있습니다.

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks[0] # "Tiger"
sharks[1] # "Great White"
sharks[-1] # "Angel"

또한 firstlast 메서드를 사용하여 배열의 첫 번째 요소와 마지막 요소를 가져올 수 있다는 것을 기억할 것입니다.

sharks = ["Tiger", "Great White", "Hammerhead", "Angel"]
sharks.first # "Tiger"
sharks.last # "Angel"

마지막으로 존재하지 않는 요소에 액세스하면 nil이 표시됩니다. 하지만 대신 오류가 발생하려면 fetch 메서드를 사용하세요.

sharks.fetch(42)
Output
IndexError: 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 요소를 지정하여 <를 포함하는 새 배열을 얻습니다.\그레이트 화이트\ 및 \해머헤드\.

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과 배열의 마지막 인덱스 사이에 임의의 인덱스를 생성하고 이를 인덱스로 사용하여 값을 검색할 수 있지만 더 쉬운 방법이 있습니다.sample 메서드는 배열에서 임의의 항목을 가져옵니다.

이를 사용하여 재고 답변 배열에서 무작위 답변을 가져와 Magic 8-Ball 게임의 기본 버전을 만들어 보겠습니다.

answers = ["Yes", "No", "Maybe", "Ask again later"]
print answers.sample
Output
Maybe

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
Output
Hammerhead

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"]

selectreject는 모두 원래 배열을 변경하지 않고 새 배열을 반환합니다. 그러나 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

ab 변수는 비교되는 배열의 개별 요소를 나타냅니다. 결과는 다음과 같습니다.

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
Output
ArgumentError: 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를 사용하는 것이 더 효율적임을 알게 될 것입니다.

sortsort_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
Output
Hammerhead Great White Tiger Whale

각 상어 이름을 쉼표 공백으로 구분하려면 쉼표와 공백을 구분 기호로 사용하십시오.

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join(", ")
print result
Output
Hammerhead, Great White, Tiger, Whale

join 메서드에 대한 인수를 지정하지 않으면 여전히 문자열을 얻지만 구분 기호는 없습니다.

sharks = ["Hammerhead", "Great White", "Tiger", "Whale"]
result = sharks.join
print result
Output
HammerheadGreat 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
Output
6

대신 reduce 메서드를 사용하여 이 작업을 수행할 수 있습니다. reduce 메서드는 배열을 반복하고 각 요소에 대해 이진 연산을 실행하여 누계를 유지합니다.

reduce 메서드는 결과에 대한 참조와 현재 요소에 대한 참조라는 두 개의 로컬 값이 있는 블록뿐만 아니라 결과에 대한 초기 값을 허용합니다. 블록 내부에서 최종 결과를 계산할 논리를 지정합니다.

배열을 합산하고 싶기 때문에 결과를 0으로 초기화한 다음 현재 값을 블록의 결과에 추가합니다.

output = [1,2,3].reduce(0) {|result, current| result += current }
print output
Output
6

결과를 0으로 초기화하려는 경우 인수를 생략하고 블록만 전달할 수 있습니다. 이렇게 하면 결과가 배열의 첫 번째 값으로 자동 설정됩니다.

output = [1,2,3].reduce {|result, current| result += current }
print output
Output
6

reduce 메소드는 또한 바이너리 메소드 또는 배열의 각 항목에 대해 실행할 다른 객체를 인수로 허용하는 한 객체의 메소드를 지정합니다. reduce는 결과를 사용하여 단일 값을 생성합니다.

Ruby에서 2 + 2를 작성하면 실제로 정수 2에 대해 + 메서드를 호출하는 것입니다.

2.+(2) # 4

Ruby는 약간의 구문 설탕을 사용하므로 2 + 2로 표현할 수 있습니다.

reduce 메서드를 사용하면 이름을 기호로 전달하여 이진 메서드를 지정할 수 있습니다. 즉, :+reduce 메서드에 전달하여 배열을 합산할 수 있습니다.

output = [1, 2, 3].reduce(:+)
print output
Output
6

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의 데이터 유형 이해