문자열 값을 포함하는 Ruby 배열이 있습니다. 다음을 수행해야합니다.
- 일부 술어와 일치하는 모든 요소 찾기
- 변환을 통해 일치하는 요소 실행
- 결과를 배열로 반환
지금 내 솔루션은 다음과 같습니다.
def example
matchingLines = @lines.select{ |line| ... }
results = matchingLines.map{ |line| ... }
return results.uniq.sort
end
선택 및 매핑을 단일 논리 문으로 결합하는 Array 또는 Enumerable 메서드가 있습니까?
답변
나는 보통 map
및 compact
내 선택 기준과 함께 접미사로 사용 if
합니다. compact
nil을 제거합니다.
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}
=> [3, 3, 3, nil, nil, nil]
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}.compact
=> [3, 3, 3]
답변
reduce
이를 위해 사용할 수 있으며 한 번만 패스하면됩니다.
[1,1,1,2,3,4].reduce([]) { |a, n| a.push(n*3) if n==1; a }
=> [3, 3, 3]
즉, 상태를 원하는대로 초기화하십시오 (이 경우 채울 빈 목록 : []
, 항상 원래 목록의 각 요소에 대한 수정 사항과 함께이 값을 반환해야합니다 (이 경우 수정 된 요소 목록에 푸시 됨).
한 번의 패스 ( map
+ select
또는compact
두 번의 패스가 필요함).
귀하의 경우 :
def example
results = @lines.reduce([]) do |lines, line|
lines.push( ...(line) ) if ...
lines
end
return results.uniq.sort
end
답변
답변
이것에 접근하는 또 다른 다른 방법은 new (이 질문과 관련하여)를 사용하는 것입니다 Enumerator::Lazy
.
def example
@lines.lazy
.select { |line| line.property == requirement }
.map { |line| transforming_method(line) }
.uniq
.sort
end
이 .lazy
메서드는 lazy 열거자를 반환합니다. 호출 .select
또는 .map
게으른 열거에 또 다른 게으른 열거를 돌려줍니다. 한 번만 호출 .uniq
하면 실제로 열거자를 강제 적용하고 배열을 반환합니다. 따라서 효과적으로 발생하는 것은 귀하 .select
와 .map
통화가 하나로 결합되는 것입니다. @lines
한 번만 반복 .select
하여.map
.
내 본능은 Adam의 reduce
방법이 조금 더 빠를 것이지만 이것이 훨씬 더 읽기 쉽다고 생각합니다.
이것의 주요 결과는 각 후속 메서드 호출에 대해 중간 배열 개체가 생성되지 않는다는 것입니다. 정상적인 @lines.select.map
상황 에서는에 select
의해 수정 된 배열을 반환하고 map
다시 배열을 반환합니다. 이에 비해 지연 평가는 배열을 한 번만 생성합니다. 이것은 초기 컬렉션 개체가 클 때 유용합니다. 또한 무한 열거 자로 작업 할 수 있습니다 random_number_generator.lazy.select(&:odd?).take(10)
.
답변
당신이있는 경우 select
사용 할 수있는 case
연산자를 ( ===
) grep
좋은 대안이다 :
p [1,2,'not_a_number',3].grep(Integer){|x| -x } #=> [-1, -2, -3]
p ['1','2','not_a_number','3'].grep(/\D/, &:upcase) #=> ["NOT_A_NUMBER"]
더 복잡한 논리가 필요한 경우 람다를 만들 수 있습니다.
my_favourite_numbers = [1,4,6]
is_a_favourite_number = -> x { my_favourite_numbers.include? x }
make_awesome = -> x { "***#{x}***" }
my_data = [1,2,3,4]
p my_data.grep(is_a_favourite_number, &make_awesome) #=> ["***1***", "***4***"]
답변
하나가 있는지 잘 모르겠습니다. 및 을 추가 하는 Enumerable 모듈 은 하나를 표시하지 않습니다.select
map
두 블록을 select_and_transform
메서드 에 전달해야하는데 , 이는 약간 직관적이지 않은 IMHO입니다.
분명히, 더 읽기 쉽게 함께 연결할 수 있습니다.
transformed_list = lines.select{|line| ...}.map{|line| ... }
답변
간단한 대답 :
당신은 n 개의 기록을 가지고 있고, 당신이 원하는 경우 select
와 map
다음 조건에 따라
records.map { |record| record.attribute if condition }.compact
여기에서 속성은 레코드에서 원하는 모든 항목과 조건을 확인할 수 있습니다.
compact는 if 조건에서 나온 불필요한 nil을 플러시하는 것입니다.