Handling Ruby’s String.each_char Iterator

Ahh the joys of iterators. I can’t say enough about how much they make my life easier. They are just so darn handy. Life was good in my Ruby world until I needed to iterate through the characters in a string. Thinking to myself, “there has got to be a method that does this,” I looked up Ruby’s String class and saw just what the doctor ordered… each_char.

Feeling pretty proud that my favorite language had this baked right in, I was only to happy to inject it into my code and test it out. That is until I recieved the dreaded NoMethodError: undefined method `each_char’ . Eeek, what did I do wrong? Did I mispell the method…..Nope, did I call it correctly…..Yep. Well, what the heck is going on?

After multiple attempts to find the answer on Google, I finally posted my problem to the ruby-talk group. I was told that the Ruby 1.8 String implementation that I was using only understood bytes and that I could use require ‘jcode’ to get the iterator to work the way I wanted. I did some looking around and I am not sure this is a great solution, after all, I could have easily used the each_byte{|f| f.chr} to iterate through and convert accordingly. I don’t understand why something that is documented as part of the class, does not work.

It would really help if there was an easy to search area on the net dedicated to language quirks for people trying to get a better grasp of their programming language of choice. Maybe that will be my next ROR project.

As it turns out, my Ruby 1.8.7 installation on my Fedora core 9 works as advertised.

14 thoughts on “Handling Ruby’s String.each_char Iterator

  1. Glad to see I’m not the only one having this problem. I agree that it shouldn’t be listed in the Core documentation if it’s, ya know, not in the core.

  2. Thanks a bunch for the info. Saved me a bunch of searching. each_byte is a good work-around.

  3. As 100% of the commenters have commented so far: THANK YOU. I am yet another person who was stuck going cross-eyed over this error. I figure another comment on this post might help google to keep this page “fresh” and high in the google stats. So thanks again!

  4. Thanks so much for posting about this error in Ruby 1.8.6. I found your posting on the front page of my Google search results [ruby string each_char]. You saved me a lot of time and frustration.

  5. Thanks man! That’s what I was looking for. 🙂
    “string”.each_byte { |f| puts f.chr }

  6. Man thank you so much for this, you have no idea how your insight helped me !

    Thanks from Brazil
    Marco

  7. Another “thanks” on the pile!

    Will, unfortunately each_byte can cause problems with multi-byte character encodings.

  8. @Nick Great comment, I don’t work with a whole lot of multi-byte character encodings. In this case, Jcode would be the way to go for Ruby 1.8. I haven’t played much with Ruby 1.9 but I am excited to play with the better supported encodings that are baked right in.

  9. If you click on the source in the docs, you get:

    # File lib/jcode.rb, line 209
    def each_char
    if block_given?
    scan(/./m) do |x|
    yield x
    end
    else
    scan(/./m)
    end
    end

    so yeah, just do “string”.scan(/./m)

  10. I needed this to do a simple cleanup of strings entered by the default io.readline call. If the user hit backspace, the \b would get added to the string along w/the characters they were trying to get rid of. Here’s an inelegant solution:

    def clean(line)
    #silly little routine to parse backspaces in the input line…
    retval = “”
    line.each_byte do |ch|
    if ch == 8 #backspace
    retval.chop!
    else
    retval << ch
    end
    end
    return retval
    end

Leave a Reply

Your email address will not be published.