Program Tip

Enumerable # collect에서 반복 건너 뛰기

programtip 2021. 1. 10. 19:31
반응형

Enumerable # collect에서 반복 건너 뛰기


(1..4).collect do |x|
  next if x == 3
  x + 1
end # => [2, 3, nil, 5]
    # desired => [2, 3, 5]

조건 next이 충족되면 배열에 collect넣는 nil반면 조건이 충족되면 반환 된 배열에 요소를 넣지 않습니다 . delete_if { |x| x == nil }반환 된 배열 을 호출하지 않고도 가능 합니까?

(Ruby 1.8.7 사용; 내 코드 발췌 부분이 많이 추상화되었습니다)


Enumerable#reject목적에 맞는 방법 이 있습니다.

(1..4).reject{|x| x == 3}.collect{|x| x + 1}

한 메서드의 출력을 다른 메서드의 입력으로 직접 사용하는 관행을 메서드 체인 이라고 하며 Ruby에서 매우 일반적입니다.

BTW, map(또는 collect)는 열거 가능한 입력을 출력에 직접 매핑하는 데 사용됩니다. 다른 수의 요소를 출력해야하는 경우 Enumerable.

편집 : 일부 요소가 두 번 반복된다는 사실에 신경 쓰이는 경우 inject(또는라는 유사한 방법 each_with_object)을 기반으로 덜 우아한 솔루션을 사용할 수 있습니다 .

(1..4).each_with_object([]){|x,a| a << x + 1 unless x == 3}

.compact배열에서 nil 인스턴스를 제거하는 결과 배열을 간단히 호출 합니다. 기존 배열을 수정하려면 (그렇지 않을 이유가 없음) 다음을 사용하십시오 .compact!.

(1..4).collect do |x|
  next if x == 3
  x
end.compact!

그냥 제안, 왜 이렇게하지 않는가 :

result = []
(1..4).each do |x|
  next if x == 3
  result << x
end
result # => [1, 2, 4]

그런 식으로 배열에서 nil 요소를 제거하기 위해 다른 반복을 저장했습니다. 도움이되기를 바랍니다 =)


다음을 사용하는 것이 좋습니다.

(1..4).to_a.delete_if {|x| x == 3}

collect + next 문 대신.


의사 결정을 도우미 메서드로 가져와 다음을 통해 사용할 수 있습니다 Enumerable#reduce.

def potentially_keep(list, i)
  if i === 3
    list
  else
    list.push i
  end
end
# => :potentially_keep

(1..4).reduce([]) { |memo, i| potentially_keep(memo, i) }
# => [1, 2, 4]

Ruby 2.7 이상

이제 있습니다!

Ruby 2.7 is introducing filter_map for this exact purpose. It's idiomatic and performant, and I'd expect it to become the norm very soon.

For example:

numbers = [1, 2, 5, 8, 10, 13]
enum.filter_map { |i| i * 2 if i.even? }
# => [4, 16, 20]

Here's a good read on the subject.

Hope that's useful to someone!

ReferenceURL : https://stackoverflow.com/questions/5152098/skip-over-iteration-in-enumerablecollect

반응형