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. :-)
Comentários
Comentários fechados.
Sem nenhum comentário.
Artigos anteriores
- Pull requests em modo raiz - sex, 22 de dezembro de 2023, 09:57:09 -0300
- Qual a idade do seu repositório? - ter, 27 de dezembro de 2022, 12:50:35 -0300
- Utilizando ctags em projetos Rails mais recentes - qui, 24 de junho de 2021, 08:23:43 -0300
- Fazendo o seu projeto brotar - seg, 15 de julho de 2019, 08:57:05 -0300
- Learn Functional Programming with Elixir - sex, 02 de março de 2018, 18:47:13 -0300
- Ambiente mínimo - Driver Driven Development - qua, 23 de agosto de 2017, 15:15:03 -0300
- Ambiente mínimo - repositórios de código - dom, 16 de abril de 2017, 13:02:14 -0300
- Ambiente mínimo - terminal e navegador - dom, 02 de abril de 2017, 21:43:29 -0300
- Utilizando muitas gems no seu projeto? - sáb, 29 de outubro de 2016, 11:57:55 -0200
- Desenvolvedores e inteligência artificial - seg, 11 de julho de 2016, 09:09:38 -0300