类似的情况在《confident ruby》里也有提到过,在使用hash的时候形成习惯,就可以避免很多奇怪的问题发生。原文地址
有三种方法可以从一个hash里得到对应key的值。在文末可以看到这三种方法的一些不同处。
第一种方法,就是大部分ruby开发者都会用到的#[]
。这个方法是我们最先学到的从hash里取值的方式。
pets = { cat: "Jess" }
pets[:cat]
# => "Jess"
如果我们想要的值不存在会发生什么情况?
pets = { cat: "Jess" }
pets[:dinosaur]
# => nil
现在要处理nil的情况:
pets = { cat: "Jess" }
pets[:dinosaur] || "They all died :("
# => "They all died :("
如果出于某些原因,一些key对应的值被设置为nil
,或者是false
,那会是什么情况?
dinosaurs = { alive?: false }
dinosaurs[:alive?] || true
# => true
如果这个key在这个hash里并不存在?我们不会明确知道这个,除非放一些守护语句(guard clause)或者一个异常处理。
第二种方法就是使用#fetch
方法。
fetch这个方法在很多方面跟#[]
是一样的,但会在key不存在或值为nil时允许设置一个默认值。
pets = { cat: "Jess" }
pets.fetch(:dinosaur, "They all died :(")
# => "They all died :("
看上去跟之前一个没太大区别,再看另一个例子:
dinosaurs = { alive?: false }
dinosaurs.fetch(:alive?, true)
# => false
#fetch
只有在key不存在的情况或者这个key对应的value值为nil的情况才会去使用设置的默认值。这里的:alive?
值是false
,所以不会返回使用默认值。
第三种是第二种的变种。在第二种情况里,#fetch
的第二个参数在任何 情况下都是会被执行的,这样有时会造成些问题。
pets.fetch(:dinosaur, Dinosaur.raise_from_the_dead!)
第二个参数会被执行。
可以这样写来避免:
pets.fetch(:dinosaur) { Dinosaur.raise_from_the_dead! }
现在就只有在没有这个: dinosaur
的情况下,才会执行block里的代码。可以减小我们的开销。
网友评论