Enumerable로 더 정교해지기

12649 단어 ruby

열거 가능이란 무엇입니까?



The Enumerable mixin provides collection classes with several traversals and searching methods, and with the ability to sort. The class must provide a method each, which yields successive members of the collection.



https://ruby-doc.org/core-2.7.1/Enumerable.html
간단히 말해서 Array, Hash, String과 같은 각각의 메소드를 가지는 클래스는 Enumerable 메소드를 가지고 있습니다.

각각을 사용하는 코드 찾기, Enumerable 메서드 사용 고려


each 를 사용하는 코드가 보이면 잠재적으로 사용하지 않고 프로시저를 다시 작성할 수 있습니다. 코드베이스의 일부를 생각한다면 그것을 찾아보십시오.
또한 적절한 Enumerable 메서드를 사용하면 코드가 정교해집니다. 내가 본 정확한 예를 보고 배워봅시다.

사용 사례


사례 1: 선택


전에



arr = [1, 2, 3, 4, 5]
new_arr = []
arr.each do |v|
  new_arr << v if v.odd?
end

p new_arr # => [1, 3, 5]

후에



new_arr = arr.select(&:odd?)

p new_arr # => [1, 3, 5]

사례 2: 지도


전에



arr = [1, 2, 3, 4, 5]
new_arr = []
arr.each do |v|
  new_arr << v * 2
end

p new_arr # => [2, 4, 6, 8, 10]

후에



new_arr = arr.map { |v| v * 2 }

p new_arr # => [2, 4, 6, 8, 10]

사례 3: 주입


전에



arr = [1, 2, 3, 4, 5]
sum = 0
arr.each do |v|
  sum += v
end

p sum # => 15

후에



arr = [1, 2, 3, 4, 5]
sum = arr.inject(:+)

p sum # => 15

사례 4: 있습니까?


전제 조건



booking_statuses는 아래와 같이 정의되며 상태 전환을 확인하려고 합니다.

booking_statuses = {
  pending: 0,
  payment_requested: 1,
  paid: 2,
  cancelled: 3
}


전에





def validate_booking_transition(passed_status)
  if passed_status == booking_statuses[:cancelled]
    allowed = [
      booking_statuses[:pending],
      booking_statuses[:payment_requested],
      booking_statuses[:paid]
    ].include?(passed_status)
  elsif ...
  .
  .
  .
end


후에




def validate_booking_transition(passed_status)
  if passed_status == booking_statuses[:cancelled]
    allowed = %i(pending payment_requested paid).any? do |v|
      passed_status == booking_statuses[v]
    end
  elsif ...
  .
  .
  .
end


사례 5: group_by



전에




arr = [{code: 'a', val: 1}, {code: 'a', val: 2}, {code: 'b', val: 3}, {code: 'b', val: 4}]
new_hash = {}
arr.each do |hash|
  k = hash[:code]
  new_hash[k] = [] if new_hash[k].nil?

  new_hash[k] << hash[:val]
end

p new_hash #=> {"a"=>[1, 2], "b"=>[3, 4]}


후에




new_hash = arr.group_by { |h| h[:code] }.transform_values { |grouped_arr| grouped_arr.map { |h| h[:val] } }

p new_hash #=> {"a"=>[1, 2], "b"=>[3, 4]}


고려 사항



각 사용 사례를 살펴보십시오. Case 1-3은 일반적인 Enumerable 메소드 소개입니다.
사례 4는 적절한 Enumerable 메서드를 사용하여 우리가 의도한 것을 표현할 수 있음을 보여줍니다.
그렇다면 사례 5에 대해 무엇을 말할 수 있습니까? 예전보다 더 똑똑해 보이죠? 아니면 더 복잡해졌습니까?
각 경우에 대해 자세히 알아보겠습니다.
루프에서,
  • 사례 1: 조건에 맞는 매개변수 추출
  • 사례 2: 각 매개변수에 2를 곱합니다
  • .
  • 사례 3: 매개변수 요약
  • 사례 4: 조건에 맞는 매개변수가 있는지 확인

  • 그것으로부터 우리는 그들이 루프 내에서 1 절차를 진행한다고 말할 수 있습니다.
    Case 5의 다른 점은 iteration 내에서 여러 절차를 수행한다는 것입니다.
    그들은
  • code를 키로 사용하는 해시 생성
  • 해시 키당 배열val 생성

  • 또한 map 메서드 내에서 transform_values를 실행합니다. 상황을 더 악화시켰습니다. 예, 계산 순서 측면에서 단일 루프에서 이중 루프를 생성합니다.
    즉, 단일 반복 내에서 여러 절차를 처리해야 하는 경우 each 계산 순서와 가독성 측면 모두에서 주도권을 가질 수 있습니다.

    Enumerable 메서드 사용의 장점을 다시 생각하십시오.


    each 보다 적절한 Enumerable 메서드를 사용하여 의도를 보다 명확하게 설명할 수 있습니다.
    그리고 많은 경우에 가독성과 유지관리가 가장 중요한 정책입니다. 왜 그것을 사용하지 않습니까?
    그리고 함수형 프로그래밍에 익숙하지 않다면 부작용에 대해 생각해 볼 수 있는 좋은 기회가 될 수도 있습니다.
    그러나 사례 5에서 보여주듯이 각각이 결국 최고의 접근 방식이 될 수 있습니다. 리팩토링을 통해 중첩된 반복을 생성하지 않도록 하십시오.

    결론



    Enumerable은 프로그래밍을 재미있게 만듭니다. 즐기다!
    In Japanese

    좋은 웹페이지 즐겨찾기