Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby select 메서드 완벽 가이드: 배열·해시 필터링부터 Rails 활용까지

Ruby의 select 메서드를 사용하면 객체 배열을 손쉽게 필터링할 수 있습니다.

예를 들어 숫자 리스트에서 짝수만 골라내야 한다면 select가 딱 맞는 도구입니다.

select 없이 작성하면 다음과 같습니다:

even_numbers = []

[1,2,3,4,5,6].each do |n|
  if n.even?
    even_numbers << n
  end
end

even_numbers

이렇게 간단한 작업에 코드가 꽤 길어지죠?

지금부터 select를 제대로 활용하는 방법을 알아보겠습니다.

Select 메서드 기본 예제

select를 사용하려면 블록이 필요합니다.

블록 안에는 true 또는 false로 평가되는 값을 반환해야 하며, select는 그 결과를 기준으로 배열 요소를 걸러냅니다.

Ruby의 불리언(Boolean) 값에 대해 더 알고 싶다면 관련 문서를 참고하세요.

예제:

[1,2,3,4,5,6].select { |n| n.even? }

앞서 소개한 첫 번째 예제와 동일한 결과를 훨씬 적은 코드로 얻을 수 있습니다.

심지어 코드를 더 줄일 수도 있습니다.

이렇게요:

[1,2,3,4,5,6].select(&:even?)

이런 축약형(& 기호)은 배열의 모든 요소에 단일 메서드를 바로 호출할 때만 사용할 수 있다는 점에 유의하세요.

참고로 select는 해시(Hash)에도 사용할 수 있습니다.

예제:

stock = {
  apples: 10,
  oranges: 5,
  bananas: 1
}

stock.select { |k, v| v > 1 }

# {:apples=>10, :oranges=>5}

여기서 k는 키(key)를, v는 값(value)을 나타냅니다.

즉, "재고가 1개보다 많은 과일을 모두 찾아줘"라고 요청하는 것과 같습니다.

다른 메서드와 조합하기

select는 다른 Enumerable 메서드와 조합해 사용할 수 있습니다.

가장 대표적인 것이 with_index입니다.

예제:

fruits = %w(apple orange banana)

fruits.select.with_index { |word, idx| idx.even? }

# ["apple", "banana"]

이렇게 하면 객체 자체가 아니라 인덱스를 기준으로 요소를 필터링할 수 있습니다.

원본 배열 직접 수정하기

배열에 select를 사용하면 항상 새로운 배열이 생성됩니다.

반면 원본 배열 자체를 변경하고 싶다면 select! 메서드를 사용하면 됩니다.

사용 방법:

fruits = %w(apple orange banana)

fruits.select! { |fruit| fruit.start_with? "a" }

# ["apple"]

느낌표(!)로 끝나는 메서드(예: select!)는 새 객체를 반환하는 대신 원본 객체를 변경합니다. 다만 이 규칙은 언어 차원에서 강제되는 것이 아니라 개발자들 사이의 암묵적인 관례일 뿐이라는 점을 기억하세요.

find vs select

select는 목록을 필터링해서 결과를 담은 배열을 얻고 싶을 때 매우 유용합니다.

그런데 객체 하나만 찾고 싶다면 어떻게 할까요?

이럴 때는 find 메서드를 사용하면 됩니다.

예제:

letters = %w(a aa aaa aaaa)

letters.find { |l| l.size == 3 }
# "aaa"

letters.find { |l| l.size == 10 }
# nil

find는 조건에 일치하는 첫 번째 요소를 반환하고, 찾지 못하면 nil을 돌려줍니다.

find_all 메서드 이해하기

find_all 메서드가 무엇인지, 그리고 findselect와 어떤 관계인지 궁금하다면...

정답은 아주 간단합니다!

  • find_all 메서드는 select의 별칭(alias)입니다.
  • find 메서드는 여러 객체가 아닌 특정 하나의 객체를 찾을 때 사용합니다.

또한 Ruby 2.6부터는 select의 또 다른 별칭으로 filter가 추가되었습니다.

filter

select의 반대는 무엇일까?

원하는 요소를 선택하는 대신, 불필요한 요소를 제거하는 접근 방식도 있습니다.

select로도 충분히 가능합니다:

[1,2,3,4,5,6].select { |n| n != 4 }

하지만 의도를 더 명확하게 드러내는 메서드가 바로 reject입니다.

예제:

[1,2,3,4,5,6].reject { |n| n == 4 }

성능 면에서나 기술적으로 이점이 있는 것은 아니지만, 코드의 가독성과 의도 전달력이 훨씬 좋아집니다.

Rails의 select 메서드 주의사항

Rails 모델을 다루다 보면 거기서도 select를 사용할 수 있다는 것을 알게 되는데, 혼동하지 않도록 주의해야 합니다.

꼭 알아두어야 할 점은...

select 메서드는 지금까지 설명한 것과 전혀 다릅니다!

예제:

Fruit.select(:id, :name, :color)

ActiveRecord 모델에 select를 사용하면 데이터베이스에서 특정 컬럼만 조회하겠다는 의미가 됩니다.

이는 주로 성능 최적화를 위해 사용되는 것으로 알려져 있습니다.

마지막으로 한 가지 덧붙이자면:

Rails 앱 안에서 일반 배열을 다루고 있다면, 이 글 전체에서 설명한 그 select 메서드를 사용하는 것입니다.

마무리

지금까지 배열, 범위(range), 해시처럼 객체 컬렉션을 다룰 때 가장 유용한 Ruby 메서드 중 하나인 select에 대해 살펴봤습니다.

Ruby select 메서드 완벽 가이드: 배열·해시 필터링부터 Rails 활용까지

이제 여러분 차례입니다. 에디터를 열고 직접 활용해 보세요!

읽어주셔서 감사합니다!