IT story

Ruby-다차원 해시 액세스 및 nil 객체 액세스 방지

hot-time 2020. 9. 13. 11:50
반응형

Ruby-다차원 해시 액세스 및 nil 객체 액세스 방지 [중복]


중복 가능성 :
Ruby : IF 문에서 Nils
중첩 된 params 해시에서 nil에 대한 메서드 호출을 피할 수있는 깨끗한 방법이 있습니까?

다음과 같은 해시에 액세스하려고한다고 가정 해 보겠습니다.

my_hash['key1']['key2']['key3']

key1, key2 및 key3이 해시 (들)에 존재하면 좋지만, 예를 들어 key1이 존재하지 않으면 어떻게 될까요?

그럼 나는 얻을 것이다 NoMethodError: undefined method [] for nil:NilClass. 그리고 아무도 그것을 좋아하지 않습니다.

지금까지 다음과 같은 조건부 작업을 처리합니다.

if my_hash['key1'] && my_hash['key1']['key2'] ...

이것이 적절합니까? 다른 루비 에스 방법이 있습니까?


이에 대한 많은 접근 방식이 있습니다.

Ruby 2.3 이상을 사용하는 경우 dig 를 사용할 수 있습니다.

my_hash.dig('key1', 'key2', 'key3')

많은 사람들이 일반 루비를 고수하고 &&가드 테스트를 연결합니다 .

stdlib Hash # fetch사용할 수 있습니다 .

my_hash.fetch('key1', {}).fetch('key2', {}).fetch('key3', nil)

일부는 ActiveSupport의 #try 메소드 연결과 같습니다 .

my_hash.try(:[], 'key1').try(:[], 'key2').try(:[], 'key3')

기타 사용 건강에 좋은

myhash['key1'].andand['key2'].andand['key3']

어떤 사람들은 자기 중심적인 nils 가 좋은 생각이라고 생각합니다 (누군가가 당신이 이것을 발견하면 당신을 사냥하고 고문 할 수도 있지만).

class NilClass
  def method_missing(*args); nil; end
end

my_hash['key1']['key2']['key3']

Enumerable # reduce (또는 별칭 주입)를 사용할 수 있습니다 .

['key1','key2','key3'].reduce(my_hash) {|m,k| m && m[k] }

또는 중첩 조회 방법을 사용하여 Hash 또는 대상 해시 개체 만 확장 할 수 있습니다.

module NestedHashLookup
  def nest *keys
    keys.reduce(self) {|m,k| m && m[k] }
  end
end

my_hash.extend(NestedHashLookup)
my_hash.nest 'key1', 'key2', 'key3'

오, 그리고 어쩌면 모나드를 어떻게 잊을 수 있습니까?

Maybe.new(my_hash)['key1']['key2']['key3']

당신은 또한 사용할 수있는 건강에 좋은 개체 #을 .

my_hash['key1'].andand['key2'].andand['key3']

조건 my_hash['key1'] && my_hash['key1']['key2']건조 함을 느끼지 않습니다 .

대안 :

1) 자생 마법. 그 게시물에서 :

def autovivifying_hash
   Hash.new {|ht,k| ht[k] = autovivifying_hash}
end

그런 다음 귀하의 예를 들어 :

my_hash = autovivifying_hash     
my_hash['key1']['key2']['key3']

It's similar to the Hash.fetch approach in that both operate with new hashes as default values, but this moves details to the creation time. Admittedly, this is a bit of cheating: it will never return 'nil' just an empty hash, which is created on the fly. Depending on your use case, this could be wasteful.

2) Abstract away the data structure with its lookup mechanism, and handle the non-found case behind the scenes. A simplistic example:

def lookup(model, key, *rest) 
    v = model[key]
    if rest.empty?
       v
    else
       v && lookup(v, *rest)
    end
end
#####

lookup(my_hash, 'key1', 'key2', 'key3')
=> nil or value

3) If you feel monadic you can take a look at this, Maybe

참고URL : https://stackoverflow.com/questions/10130726/ruby-access-multidimensional-hash-and-avoid-access-nil-object

반응형