Стиль Ruby: Как проверить, существует ли вложенный элемент хеша

Некоторые компиляторы имеют различные размеры для интервала на различных платформах (не конкретный C#)

, Некоторые стандарты кодирования (MISRA C) требуют, чтобы все используемые типы были определенным размером (т.е. Int32 и не интервал).

также хорошо определить префиксы для переменных другого типа (например, b для байта на 8 битов, w для слова на 16 битов и l для длинного слова на 32 бита => Int32 lMyVariable)

, необходимо заботиться, потому что это делает код более портативным и более удобным в сопровождении.

Портативный может не быть применимо к C#, если Вы всегда собираетесь использовать C#, и спецификация C# никогда не будет изменяться в этом отношении.

Удобный в сопровождении ihmo всегда будет применим, потому что человек, поддерживающий Ваш код, не может знать об этой конкретной спецификации C#, и отсутствовать, ошибка был интервал, иногда становится больше чем 2 147 483 647.

В простом для цикла, который считает, например, месяцы года, Вы не будете заботиться, но когда Вы будете использовать переменную в контексте, где это могло возможно переполниться, необходимо заботиться.

необходимо также заботиться, собираетесь ли Вы сделать битовые операции на нем.

56
задан Gaurav Sharma 18 December 2013 в 07:56
поделиться

5 ответов

The most obvious way to do this is to simply check each step of the way:

has_children = slate[:person] && slate[:person][:children]

Use of .nil? is really only required when you use false as a placeholder value, and in practice this is rare. Generally you can simply test it exists.

Update: If you're using Ruby 2.3 or later there's a built-in dig method that does what's described in this answer.

If not, you can also define your own Hash "dig" method which can simplify this substantially:

class Hash
  def dig(*path)
    path.inject(self) do |location, key|
      location.respond_to?(:keys) ? location[key] : nil
    end
  end
end

This method will check each step of the way and avoid tripping up on calls to nil. For shallow structures the utility is somewhat limited, but for deeply nested structures I find it's invaluable:

has_children = slate.dig(:person, :children)

You might also make this more robust, for example, testing if the :children entry is actually populated:

children = slate.dig(:person, :children)
has_children = children && !children.empty?
85
ответ дан 26 November 2019 в 17:12
поделиться

You can use the andand gem:

require 'andand'

fred[:person].andand[:children].nil? #=> false
dino[:person].andand[:children].nil? #=> true

You can find further explanations at http://andand.rubyforge.org/.

4
ответ дан 26 November 2019 в 17:12
поделиться

Вы можете попробовать поиграть с

dino.default = {}

Или, например:

empty_hash = {}
empty_hash.default = empty_hash

dino.default = empty_hash

Таким образом вы можете позвонить

empty_hash[:a][:b][:c][:d][:e] # and so on...
dino[:person][:children] # at worst it returns {}
0
ответ дан 26 November 2019 в 17:12
поделиться
dino_has_children = !dino.fetch(person, {})[:children].nil?

Обратите внимание, что в рельсах вы также можете делать:

dino_has_children = !dino[person].try(:[], :children).nil?   # 
1
ответ дан 26 November 2019 в 17:12
поделиться

One could use hash with default value of {} - empty hash. For example,

dino = Hash.new({})
dino[:pet] = {:name => "Dino"}
dino_has_children = !dino[:person][:children].nil? #=> false

That works with already created Hash as well:

dino = {:pet=>{:name=>"Dino"}}
dino.default = {}
dino_has_children = !dino[:person][:children].nil? #=> false

Or you can define [] method for nil class

class NilClass
  def [](* args)
     nil
   end
end

nil[:a] #=> nil
2
ответ дан 26 November 2019 в 17:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: