ruby using the "&:methodname" shortcut from array.map(&:methodname) for hash key strings rather than methodname

StackOverflow https://stackoverflow.com/questions/20179636

  •  04-08-2022
  •  | 
  •  

Question

Most ruby developers know how to save a few keystrokes by doing something like this:

array.map(&:methodname)

rather than

array.map {|x| x.methodname }

Is there any way I could apply a similar &:methodname shortcut for calling "methods" (values called via keys) on an array of hashes?

In my case its with JSON api results being returned in batches of 60 as arrays of hashes originating from JSON. I tried to do this:

array.map(&:"keyname")

but was not successful, throwing a NoMethodError and saying that there's no 'keyname' method for Hash, which is reasonable I guess. I'm wondering if there is some magic bullet to emulating this &:... shortcut for hashes that the ruby guys have already worked out.

Here's one of the actual JSON responses, limited to 5 results I think

[{"geometry":{"location":{"lat":33.723008,"lng":-78.930593}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/bowling-71.png","id":"095e108208879fe989f2b36e81e38bafe0c17574","name":"Waccamaw Bowling Center","opening_hours":{"open_now":true},"photos":[{"height":612,"html_attributions":["\u003Ca href=\"https://plus.google.com/106701205257534874835\"\u003EAndy Badi\u003C/a\u003E"],"photo_reference":"CoQBeQAAANZ3d4xBep-4jlCnHp0IcCfSr4k6WVnAMDkPNPhlhSTaZ-NICdLaPVxaRW04qK8ko8x5SDScTeImNKWo2qlyF0JYTQpy-elxdZkx58BYQsjCLdtOaBr_yIoKk3NSuBGk7RS9Lf2IWpW0NaBjeAcPTNdKKHoTt_PZ4212cD67wV0jEhBmRx62d9nUyBmPkrv51nadGhTXEhV-hA5frdzGKal4tEd2pYPtjQ","width":816}],"rating":3.1,"reference":"CoQBeAAAAD5d1gIGf4AG427DlKp-AC74Wt5ZCTd6uPU0-31qTnDRW3mBk4Scq00zjaLpbXnqvs1rlMgEFHPVId9nPGU5oaWr2nYRqRodz5LGdVpZqHx1R_PRciZX7xb068t6c7bqw7Fy_Bs9YIi8pCNdfAdHEZb8Pjxy1mpnL1qN_DBz243eEhCrzUmU34savXzZijjlv8TzGhSX3SofvWtuGYOhhPol9atp3aTSyQ","types":["bowling_alley","establishment"],"vicinity":"101 Philip Gray Drive, Myrtle Beach"},{"geometry":{"location":{"lat":33.817622,"lng":-78.692496}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/bowling-71.png","id":"12fed6fbc66c7d9fc693fe37e6834e32ee6e23b9","name":"North Myrtle Beach Bowling Center","photos":[{"height":460,"html_attributions":["\u003Ca href=\"https://plus.google.com/100443525307746960711\"\u003EHolly Heniford\u003C/a\u003E"],"photo_reference":"CpQBhwAAADY5u5bWSEVGRZr1A7LR0Dpli5EEDRvOt5oWvzQYCOvRk1XO9bMBPdKvQYy_TwSHDcRRcqo6JZoGyLc-nLvlOoG1gX133KkdJ7lKU33RC9hdeN_dzfAUoxIrArZK8Ssu2QQWpXmq10xsJKPIu2bAzpS3n3vKqLdeKZY86GPw7LR0cM-Su3P0MZiY2AkC7uIJIhIQkQVG3s7We7yNPlqRqBkE4xoULTYXh2O6PPuki5_TXG3tN1O3kLg","width":816}],"reference":"CpQBgwAAAB0eZVssHlDn56UET5IqUpZygTzWdLclQ73lU0xzgNG875YyQPhQWGvOI2ciZq_BO6yZYzjMIdGEFVI-jnOhj_Y56Eq0T1MaLAL0dIkCM9qS4QwjAv3-TjwJOMBnN7aARHr3BuGqYLQZb5fkN3veUr2tWLKDZcPT1SHXRLypDutO5msurlQLub5YgmNhOomPdxIQLbIFLMxiqssFIUbO6bEcrRoU0A49j-VRMk4vHsSqxADOq5OPo1o","types":["bowling_alley","establishment"],"vicinity":"1105 Highway 17S, North Myrtle Bch"},{"geometry":{"location":{"lat":33.617718,"lng":-78.976797}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/bowling-71.png","id":"5b2bcc16481ea7519f5e2858d4aa8af1b836f3c8","name":"Surfside Bowling Center","rating":4.4,"reference":"CoQBeQAAACW_aubzCjtG19Nw9Pm9RIXpzpgXD5rFyKziCYy0Uc7X9g1vVz2YWoDUmXwIYA9uUksSArTypwe8lh76TjYYTnNIPiTXc_dpgw94XGaQwC1dO5DuMBPLtWyKgY4Jqa8UlYdHnTOe4FPJnZV7gTsx25Eid2iasa07gruGui6tltYtEhBpBraa9i7GzEE3FUYWxUU0GhSsfU66SAn8tpT3Oa_PRkTUYLXlCQ","types":["bowling_alley","establishment"],"vicinity":"510 U.S. 17 Business, Surfside Beach"},{"geometry":{"location":{"lat":33.580683,"lng":-79.024837}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/bowling-71.png","id":"259104d58ff8e1aebe70db6149c74c736500a069","name":"Frank Theatres","opening_hours":{"open_now":true},"photos":[{"height":400,"html_attributions":[],"photo_reference":"CnRnAAAAq26m02SGow16WCPVIvqioB646tx-kq39g-KPZ6rydR4gUFS2eFF_M3f0-ntrLiq-Iv3jjiQfUdVt_qMxYSAxxOxhfW9JucBG9-Z4ddJH-teNg6p62rHu5Ebbxs-CI40xoK78w3rdLbYA6GsWaOL5gRIQ5UBFXus-gXSy1UrWQ_aiixoUFE0H2eqxYpFyzbGkQtbq4nUHgUk","width":300}],"reference":"CnRvAAAAMDm7HoTk9pG-nKJGvzl9QIw6Qhso44Nh5Q0-xOwM5rykjQ12DJiF_2vZRMaUk9bOtNJwW9ntoBpTgj6bHtWiVCP3OlMu-gd0dgMygMvrIxGTkaR3cTKab0KuHHnoCFxdVB7esI-rK0v585lWS6xTZxIQ0gFfzO3vhZGkIjF6ThDgNBoUAYAMJyjC7f__SBcqOLKbDl3pFSQ","types":["bowling_alley","restaurant","food","movie_theater","establishment"],"vicinity":"10125 Frontage Road #12f, Murrells Inlet"},{"geometry":{"location":{"lat":33.959856,"lng":-78.400399}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/bowling-71.png","id":"39a632e654125e6aa73a526579cae55cc14ee4a2","name":"Brunswick County Bowling Center","reference":"CoQBgAAAAETfTwuwFT34ynta7FJFME2kBVM0XurlJJKj3IQMaOXlWqTGU2P2L4l3gX9XP3XkGSgbxsQiOxIpGiTkrKRVV_-EzvGMNeE8IpsmSUMY7SBY-w7SlC6DGtlX1Py-YES6ZSTrM36my9f6Y2s7bAqamlvXbdtGfTgJpycuI0cx28fvEhB7Y-gtYgRCIInlgHxli4ygGhQlgaJt7d4PylH0KJBnzjRJeIKbNA","types":["bowling_alley","establishment"],"vicinity":"630 Village Rd SW, South Brunswick"},{"geometry":{"location":{"lat":33.974945,"lng":-78.396355}},"icon":"http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png","id":"abaf128a51021a535a17b1af4a523a5fc3af7d10","name":"Planet Fun","photos":[{"height":485,"html_attributions":[],"photo_reference":"CnRtAAAACFYcotbimoFO1Jrqiy7PgLZ3Uuq4t1BLKvrewRdsV0aUZ4ay1jwtCaDQ-q2sh7EweO5At2YA3Mg-tukES9UXItwOn2uLD2sXenKg2UhkBSwa-bvd4RGAH-dg0uACDU_0_kCi7xHkv5WrgSiKmBVN8hIQYBr23I1W9dOQ5F6Rdn1wfRoUVBdp3FEoKA_0e29nzlnUem15BJs","width":1024}],"rating":2.8,"reference":"CnRrAAAARZu90zQ_rp_pRX80BxqorM2GecSJ9kUkRnWNWEDx5K5JXwe9qgPdkzMsq8yOxITR1iPmS6knSWKNO-eWhYxBtJSti7O0ar1kkK2lBUhS5Kn6AxuT8bxlyuKLSuiGN3Zi-YFXI6d4nxhL7uO3K8LAnxIQNJ5TMpFhegaM3saANGrubBoUD7D9lw61ng3SmpK4g1dzf1cIVJ4","types":["amusement_park","establishment"],"vicinity":"349 Whiteville Road Northwest, Shallotte"}]
Was it helpful?

Solution

You can do this with a lambda:

extract_keyname = ->(h) { h[:keyname] }
ary_of_hashes.map(&extract_keyname)

This tends to be more useful if the block's logic is more complicated than simply extracting a value from a Hash. Also, attaching names to your bits of logic can help clarify what a chain of Enumerable method calls is trying to do.

You can also have a lambda which returns a lambda if you're doing this multiple times:

extract = ->(k) { ->(h) { h[k] } }
ary_of_hashes.map(&extract[:keyname])
ary_of_hashes.map(&extract[:other_key])

or a lambda building method:

def extract(k)
  ->(h) { h[k] }
end

ary_of_hashes.map(&extract(:keyname))
ary_of_hashes.map(&extract(:other_key))

OTHER TIPS

If you are working with ruby on rails, you can use the Enumerable#pluck method, which is implemented by ActiveSupport. This will allow you to do the following:

array_of_hashes = [{a: 1, b: 2}, {a: 3,b: 4}, {a: 5, b: 6}]
=> [{:a=>1, :b=>2}, {:a=>3, :b=>4}, {:a=>5, :b=>6}]

array_of_hashes.pluck(:b)
=> [2, 4, 6]

See the documentation here: https://www.rubydoc.info/gems/activesupport/5.0.0/Enumerable:pluck

& before a statement in a line of ruby is a shortcut of calling to_proc.

On a symbol to_proc looks for the method on the "context" and calls uses that as reference.

also:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top