Hashes Ruby com valores default
Publicado em Developer
Vivendo e aprendendo. Hoje estava lendo um post no site do Eigenclass e não havia me tocado de todas as possibilidades do Hash.new. Olha que barato.
O primeiro comportamento do Hash.new, o mais conhecido, é retornar um valor nil sempre que é requisitada uma chave que não existe na Hash:
[taq@~]irb irb(main):001:0> h = Hash.new => {} irb(main):002:0> h["a"] = 100 => 100 irb(main):003:0> h["b"] = 200 => 200 irb(main):004:0> h["a"] => 100 irb(main):005:0> h["b"] => 200 irb(main):006:0> h["c"] => nil irb(main):007:0> h => {"a"=>100, "b"=>200}
Até aí tudo bem. Mas o Hash.new permite também que alteremos esse valor default:
[taq@~]irb irb(main):001:0> h = Hash.new("Inexistente") => {} irb(main):002:0> h["a"] = 100 => 100 irb(main):003:0> h["b"] = 200 => 200 irb(main):004:0> h["a"] => 100 irb(main):005:0> h["b"] => 200 irb(main):006:0> h["c"] => "Inexistente" irb(main):007:0> h => {"a"=>100, "b"=>200}
Agora a parte legal é que podemos retornar o valor default utilizando blocos (ah, os blocos!):
[taq@~]irb irb(main):001:0> h = Hash.new {|h,k| "#{k} foi pescar."} => {} irb(main):002:0> h["a"] = 100 => 100 irb(main):003:0> h["b"] = 200 => 200 irb(main):004:0> h["a"] => 100 irb(main):005:0> h["b"] => 200 irb(main):006:0> h["c"] => "c foi pescar." irb(main):007:0> h => {"a"=>100, "b"=>200}
E uma parte mais legal ainda é que ali no bloco passamos a referência da Hash também, então podemos, se quisermos, incluir um elemento novo nela com a chave especificada e o valor default:
[taq@~]irb irb(main):001:0> h = Hash.new {|h,k| h[k] = "#{k} foi pescar."} => {} irb(main):002:0> h["a"] = 100 => 100 irb(main):003:0> h["b"] = 200 => 200 irb(main):004:0> h["a"] => 100 irb(main):005:0> h["b"] => 200 irb(main):006:0> h["c"] => "c foi pescar." irb(main):007:0> h => {"a"=>100, "b"=>200, "c"=>"c foi pescar."}
Resumindo um pouco o exemplo do post que mencionei, e fazendo algo mais sensato do que esses valores default doidos, o que o sujeito fez foi criar uma Hash onde quando um IP é requisitado na chave, ele é adicionado na chave e armazenao nome do país no valor, utilizando o GeoIP:
[taq@~]irb irb(main):001:0> h = Hash.new {|h,k| h[k] = `geoiplookup #{k}`.chomp.gsub( /^GeoIP Country Edition: /,"") } => {} irb(main):002:0> h["200.211.78.150"] => "BR, Brazil" irb(main):003:0> h["216.236.37.99"] => "US, United States" irb(main):004:0> h["217.12.3.11"] => "GB, United Kingdom" irb(main):005:0> h => {"217.12.3.11"=>"GB, United Kingdom", "200.211.78.150"=>"BR, Brazil", "216.236.37.99"=>"US, United States"}
Ah, dá para retornar o valor default usando ... Hash.default também. :-) Seguindo o exemplo acima:
irb(main):006:0> h.default Usage: geoiplookup [-v] <ipaddress|hostname> => "" irb(main):007:0> h.default("212.80.177.133") => "ES, Spain" irb(main):008:0> h => {"217.12.3.11"=>"GB, United Kingdom", "200.211.78.150"=>"BR, Brazil", nil=>"", "216.236.37.99"=>"US, United States", "212.80.177.133"=>"ES, Spain"}
Legal, hein. :-)
Tags:
Comentários
Comentários fechados.
Sem nenhum comentário.