Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Andrew Stelmach
12,583 PointsRuby Hashes Extra Credit. Too hard?
"Write a function that converts hashes with string keys into hashes with symbols as keys. The function should work recursively."
I've been having a go at this, but I'm on the verge of giving up.
I've been googling to help myself, and there does seem to be some solutions on various forums, but I'd just be copy/pasting without really understanding what's going on.
At this stage of the tutorial it seems a bit too hard. Unless I'm missing something? I've been experimenting with myhash.map and myhash.each_key, but basically I'm pretty stumped.
5 Answers
Andrew Stelmach
12,583 PointsI did it Maciej!!!
I am SO pleased, I had a little celebration. Us English people would say, "YOU BEAUTY!!!". But even though I'm not Scottish, I prefer the Scot's "YA DANCAAAAA", which means "you dancer", which translates to, "I'm really really pleased."
Thanks for all your help - you provided just enough help, without helping 'too much'.
myhash = {"Name"=>"Andy", "Sex"=>"Male", "Status"=>"Awesome"}
def convert(myhash)
@newhash = {}
myhash.map do |key, value|
newkey = key.to_sym
newvalue = value
@newhash[newkey]=newvalue
end
end
convert(myhash)
puts @newhash
Having said all that, PLEASE don't be afraid to criticise my code. Can you see any problems with it?
I used @ to make newhash accessible outside of the method. It's the only way I know to achieve that. Is there another way to make the newhash accessible outside of the method?
Maciej Czuchnowski
36,441 PointsI can give you some hints. You can then read up on the methods, experiment with these and see if you can get it to work.
Start with defining the method and making it accept an argument (which will be a hash in this case). Something like this:
def convert(hash)
//your code
end
There is a thing called .map and it looks like this:
hash.map { |key,value|
// your code here
}
This allows you to do things to each key and value of the hash that you have in the hash variable.
There is also a method that lets you convert things into symbols: .to_sym, which will be useful here.
At least this is the way I would do it. There are probably other approaches to this. Those extra credit things are always harder and they use stuff that isn't in the videos.
Andrew Stelmach
12,583 PointsIt looks like I'll have to come back to this after I've gone through the Method module - this is what I mean - this task seems out of sync with the tutorials. I know I'm complaining here, but I'm not one for complaining for the sake of it (I do believe in the 'stop whining and get on with it' approach) - I'm just feeding back that the extra credit things could be better constructed.
I'll get on with getting on with it now ;-) Thanks for the advice, it will help a lot and I'll post up my code here once I've solved the problem.
Andrew Stelmach
12,583 PointsI don't understand why I should use .map instead of .each_key? In my code below, using either gives the same result.
Maciej Czuchnowski
36,441 PointsLike I said, .map is something I know and something I would use, there are probably more ways to do it :). Although, I'm not sure how to use each_key to return the whole hash. I only tried this with map and it worked for me.
Andrew Stelmach
12,583 PointsI'm still having trouble with this. I don't want to be given the answer (I haven't looked at Bill's link yet! :-) ), I'd rather be given hints and have specific questions answered. So:
@myhash = {"Name"=>"Andy", "Sex"=>"Male", "Status"=>"Awesome"}
def convert
@myhash.each_key do |key|
key.to_sym
print key.class
end
end
convert
This returns StringStringString Which means that the keys were NOT converted to symbols! Why?
This doesn't make sense in light of:
@myhash = {"Name"=>"Andy", "Sex"=>"Male", "Status"=>"Awesome"}
def convert
@myhash.each_key do |key|
key="newkey"
print key
end
end
convert
This returning newkeynewkeynewkey !
Why does my method for converting each key into "newkey" works, but my method for converting the keys into symbols NOT work?!
Andrew Stelmach
12,583 PointsOk, I solved this problem, with some experimentation, BUT I REALLY NEED SOMEONE TO EXPLAIN WHY.
So, it was solved simply by using key = key.to_sym instead of just key.to_sym
@myhash = {"Name"=>"Andy", "Sex"=>"Male", "Status"=>"Awesome"}
def convert
@myhash.each_key do |key|
key = key.to_sym
print key.class
end
end
convert
This returns SymbolSymbolSymbol
Maciej Czuchnowski
36,441 PointsSo, in Ruby, there are two kinds of methods. Some methods just do stuff, return the result, but don't modify the object they are used on (they just return the new value in the line they are called, and in the next line, the object is back to its original form) and in many cases, these same methods have a parallel method which ends with the ! symbol ("unsafe methods") and such methods permanently change the object it was used on. The method you used here:
key.to_sym
is a "safe" method, which means it does not modify the key object - it just returns the key as symbol in this line, and after this line the key is back to its original form (String). But if you assign this returned value to the key variable (key = key.to_sym), it will be changed permanently, so in the next line, you no longer have a string - you have a symbol and so Symbol class is returned. Hope this helps. (not sure if there's an unsafe version of to_sym, I just mentioned "unsafe" methods as a general tip I learned at some point ;) ).
Andrew Stelmach
12,583 PointsThanks Maciej. It makes sense.
What I'm trying to work out now, is how to PERMANENTLY alter the keys i.e. change them into symbols inside the method (like I have), but when running 'puts "Name".class' for example, afterwards, outside the method, I want it to return 'Symbol'.
Any hints?
Maciej Czuchnowski
36,441 PointsI would suggest simply building a completely new hash, at each iteration putting a modified key and value from the original hash, and then returning that new hash instead of making a permanent change to the original one.
Andrew Stelmach
12,583 PointsYep, I had a similar idea. Thanks for the confirmation. My head hurts, but I'll be the happiest man alive when I finally solve this thing.
Bill Hinostroza
19,273 PointsYeah, I also was a bit confused with this because ' .to_sym ' was never introduced in the videos. Other, then that everything else is self explanatory thanks to Maciej advice.
I found a solution here (http://stackoverflow.com/questions/8379596/how-do-i-convert-a-ruby-hash-so-that-all-of-its-keys-are-symbols)
Matthew Thompson
4,500 PointsI also spent ages on this reading all the forum posts. I eventually came across this, which is an alternative to the OP solution. I did copy it but the journey to understanding how it works is important part for me.
matthash = {"name" => "Matt", "superhero" => "batman"}
def convert(matthash)
@newhash = {}
@newhash = matthash.map {|key, value| [key.to_sym, value]}.to_h
end
convert(matthash)
puts "Original hash #{matthash}"
puts "Converted hash #{@newhash}"
Maciej Czuchnowski
36,441 PointsMaciej Czuchnowski
36,441 PointsCongrats, Andrew :). I can't see anything wrong with your code, but then again, I'm not a real developer yet :).
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsMind telling me why you used an instance variable? I thought you only use that when you initialize something in a class. Why did you use it in a basic method rather then a regular variable to set the array too?
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsAlphonse Cuccurullo it's to do with Scope, as I alluded to in the answer. However, off the top of my head, I'm not exactly sure why. I'm sure I could find out with some googling, but I suggest you do that yourself and tell me if you're still stumped and why and I'll help you out.
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsStill stumped
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsAlphonse Cuccurullo I can't help you unless you tell me what you've done to try to 'unstump' yourself and what exactly it is that you don't understand.
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsI just wanna know the purpose behing you using the @newhash rather then just hash = []. That's all really.
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsI just wanna know the purpose behing you using the @newhash rather then just hash = []. That's all really.
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsAlphonse Cuccurullo, again, it's to do with Scope, as I alluded to in the answer. However, off the top of my head, I'm not exactly sure why. I'm sure I could find out with some googling, but I suggest you do that yourself and tell me if you're still stumped and why and I'll help you out.
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsI dont know what you mean by scope bro. More specific detail's would be fantastic.
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsAlphonse Cuccurullo. Dude, you really need to get into the habit of googling so you can get good at it. If/when you become professional, you still have to do that all the time. Being good at googling to learn stuff is just as important a skill as knowing how to use git, for example. No joke.
This might sound harsh, but it's for your own good. You don't know what Scope means, so google "ruby scope".
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsAlphonse Cuccurullo I've just realised that this solution isn't recursive anyway.
I've gone to the trouble of creating some homework for you that I think will be a very useful exercise for you, for a number of reasons.
I've created a repo with a non-recursive solution. The solution is verified using a test I created with rspec.
Follow the instructions in the Readme to clone the repo to your laptop and get to the point where you can run rspec to execute the test. That's the first task.
Second is to rewrite the convert method so it's recursive. Google recursive to find out what that means.
Here's the repo: https://github.com/Yorkshireman/string_keys_to_syms
Whenever you make a change to the convert method, you can check if it works properly by just running rspec. You simply rewrite the method so it's recursive - you'll know it's correct if the test still passes.
Alphonse Cuccurullo
2,513 PointsAlphonse Cuccurullo
2,513 PointsLol thanks for the help man and tolerating me as well greatly appreciate it. Had no idea there were that many different types of variable's. I am fairly new at coding i think i just gotta take one thing at a time to get it crammed into my mind. Coding is stressful especially when you gotta keep a eye on all the pieces of syntax that synergize with eachother.