다음과 같은 해시가 있습니다.
params = { :irrelevant => "A String",
:choice1 => "Oh look, another one",
:choice2 => "Even more strings",
:choice3 => "But wait",
:irrelevant2 => "The last string" }
그리고 선택하지 않은 모든 키를 거부하는 간단한 방법이 필요합니다. choice1 또는 choice1-choice10 일 수 있습니다. 그건 다양하다.
단어 선택과 그 뒤에 숫자 또는 숫자로 키를 어떻게 구분합니까?
보너스:
탭 (\ t)을 구분 기호로 사용하여 해시를 문자열로 바꿉니다. 나는 이것을했지만 몇 줄의 코드가 필요했다. 보통 마스터 Rubicians는 한 줄 정도에 그것을 할 수 있습니다.
답변
원래 답변으로 편집 :이 답변은 (이 코멘트 시점 현재) 선택된 답변이지만,이 답변의 원래 버전은 구식입니다.
나는 다른 사람들이 내가 한 것처럼이 답변에 의해 회피되지 않도록 업데이트를 여기에 추가하고 있습니다.
다른 답변에서 언급했듯이 Ruby> = 2.5 Hash#slice
는 이전에 Rails에서만 사용할 수 있었던 방법을 추가했습니다 .
예:
> { one: 1, two: 2, three: 3 }.slice(:one, :two)
=> {:one=>1, :two=>2}
편집이 끝났습니다. 다음은 Rails가없는 Ruby <2.5 인 경우 유용 할 것으로 예상되는 원래의 대답입니다.
Ruby를 사용하는 경우이 select
방법을 사용할 수 있습니다 . 정규식 일치를 수행하려면 키를 Symbol에서 String으로 변환해야합니다. 그러면 선택 사항만으로 새로운 해시가 제공됩니다.
choices = params.select { |key, value| key.to_s.match(/^choice\d+/) }
또는 delete_if
기존 해시를 사용 하고 수정할 수 있습니다.
params.delete_if { |key, value| !key.to_s.match(/choice\d+/) }
또는 원하는 값이 아닌 키 일 경우 다음을 수행 할 수 있습니다.
params.keys.select { |key| key.to_s.match(/^choice\d+/) }
그리고 이것은 단지 키의 배열을 줄 것입니다. [:choice1, :choice2, :choice3]
답변
Ruby에서 Hash # select는 올바른 옵션입니다. Rails를 사용한다면 Hash # slice와 Hash # slice!를 사용할 수 있습니다. 예 (레일 3.2.13)
h1 = {:a => 1, :b => 2, :c => 3, :d => 4}
h1.slice(:a, :b) # return {:a=>1, :b=>2}, but h1 is not changed
h2 = h1.slice!(:a, :b) # h1 = {:a=>1, :b=>2}, h2 = {:c => 3, :d => 4}
답변
가장 쉬운 방법은 gem 'activesupport'
(또는 gem 'active_support'
) 를 포함하는 것 입니다.
그런 다음 수업 시간에
require 'active_support/core_ext/hash/slice'
그리고 전화
params.slice(:choice1, :choice2, :choice3) # => {:choice1=>"Oh look, another one", :choice2=>"Even more strings", :choice3=>"But wait"}
버그가있을 수있는 다른 함수를 선언하는 것은 가치가 없으며 지난 몇 년 동안 조정 된 방법을 사용하는 것이 좋습니다.
답변
가장 쉬운 방법은 gem ‘activesupport'(또는 gem ‘active_support’)를 포함하는 것입니다.
params.slice(:choice1, :choice2, :choice3)
답변
레일 작업을하고 별도의 목록에 키가있는 경우 다음 *
표기법을 사용할 수 있습니다 .
keys = [:foo, :bar]
hash1 = {foo: 1, bar:2, baz: 3}
hash2 = hash1.slice(*keys)
=> {foo: 1, bar:2}
다른 답변에서 언급했듯이 slice!
해시를 수정하고 지운 키 / 값을 반환하는 데 사용할 수도 있습니다 .
답변
이것은 완전한 원래 질문을 해결하는 한 줄입니다.
params.select { |k,_| k[/choice/]}.values.join('\t')
그러나 위의 대부분의 솔루션은 slice
간단한 정규 표현식을 사용하여 미리 키를 알아야하는 경우를 해결합니다 .
다음은 간단하고 복잡한 유스 케이스에 작동하는 다른 접근법 입니다. 런타임시 스왑 가능
data = {}
matcher = ->(key,value) { COMPLEX LOGIC HERE }
data.select(&matcher)
이제 이것은 키 또는 값을 일치시키는 데 더 복잡한 논리를 허용 할뿐만 아니라 테스트하기도 더 쉬우 며 런타임시 일치하는 논리를 바꿀 수 있습니다.
원래 문제를 해결하기위한 Ex :
def some_method(hash, matcher)
hash.select(&matcher).values.join('\t')
end
params = { :irrelevant => "A String",
:choice1 => "Oh look, another one",
:choice2 => "Even more strings",
:choice3 => "But wait",
:irrelevant2 => "The last string" }
some_method(params, ->(k,_) { k[/choice/]}) # => "Oh look, another one\\tEven more strings\\tBut wait"
some_method(params, ->(_,v) { v[/string/]}) # => "Even more strings\\tThe last string"