Forum: Ruby iterate chars in a string

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
55a00215b8ae70a9135cfb99f42018c5?d=identicon&s=25 shinya (Guest)
on 2005-12-20 10:53
(Received via mailing list)
Hi there!
I'm a ruby newbie, and I'm searching for a way to iterate every char in
a string, but I cannot find any easy way. My problem is to look at every
char in a string and match it with some known letter.
I use the String#each_byte iterator for now, but it still be a poor
solution :/
Thanks,

shinya.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2005-12-20 10:59
(Received via mailing list)
On Dec 20, 2005, at 4:52 AM, shinya wrote:

> Hi there!
> I'm a ruby newbie, and I'm searching for a way to iterate every
> char in a string, but I cannot find any easy way. My problem is to
> look at every char in a string and match it with some known letter.
> I use the String#each_byte iterator for now, but it still be a poor
> solution :/
> Thanks,
>
> shinya.
>

The usual idiom is str.split(//).each do |character|
                # do stuff with character
           end

eg:

logan:/Users/logan% irb
irb(main):001:0> str = "Hello, world!"
=> "Hello, world!"
irb(main):002:0> str.split(//).each do |character|
irb(main):003:1*    puts character
irb(main):004:1> end
H
e
l
l
o
,
w
o
r
l
d
!
=> ["H", "e", "l", "l", "o", ",", " ", "w", "o", "r", "l", "d", "!"]

if the extraneous typing bothers you, you can always add it to String.

class String
     def each_char(&block)
            split(//).each(&block)
            self
     end
end
55a00215b8ae70a9135cfb99f42018c5?d=identicon&s=25 shinya (Guest)
on 2005-12-20 11:14
(Received via mailing list)
Logan Capaldo wrote:
>
> The usual idiom is str.split(//).each do |character|
>                # do stuff with character
>           end
>

Thank you very much! I did it :)
bye!

shinya.
Ad97b577f331ae29ed90da5751f2e44f?d=identicon&s=25 Dan Diebolt (dandiebolt)
on 2005-12-20 11:50
(Received via mailing list)
"hello world".each_byte{|i| puts "%c" % i}
D9179cdd918879d0510dfc56411e4772?d=identicon&s=25 Mark Hubbart (Guest)
on 2005-12-20 12:24
(Received via mailing list)
On 12/20/05, Logan Capaldo <logancapaldo@gmail.com> wrote:
> >
> > shinya.
> >
>
> The usual idiom is str.split(//).each do |character|
>                 # do stuff with character
>            end

String#scan with a block is lighter weight, and less wordy:
str.scan(/./) do |character|
  # stuff
end
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2005-12-20 12:36
(Received via mailing list)
On Dec 20, 2005, at 6:21 AM, Mark Hubbart wrote:

>>> Thanks,
>   # stuff
> end

str = "Hello\nWorld"

str.scan(/./) do |character|
     p character
end

irb(main):015:0> str.scan(/./) do |character|
irb(main):016:1*   p character
irb(main):017:1> end
"H"
"e"
"l"
"l"
"o"
"W"
"o"
"r"
"l"
"d"

Where'd my newlines go? :(

irb(main):021:0> str.split(//).each do |character|
irb(main):022:1*  p character
irb(main):023:1> end
"H"
"e"
"l"
"l"
"o"
"\n"
"W"
"o"
"r"
"l"
"d"

If you want to use scan, you should use scan(/./m)

irb(main):024:0> str.scan(/./m) do |character|
irb(main):025:1*   p character
irb(main):026:1> end
"H"
"e"
"l"
"l"
"o"
"\n"
"W"
"o"
"r"
"l"
"d"
E0ed615bd6632dd23165e045e3c1df09?d=identicon&s=25 =?ISO-8859-1?Q?Florian_Gro=DF?= (Guest)
on 2005-12-20 22:30
(Received via mailing list)
Logan Capaldo wrote:

> "r"
> "l"
> "d"
>
> Where'd my newlines go? :(

Heh, good point. Thanks for mentioning this. I think this might be quite
a common pit fall.

Time to grep my code and see if this could possibly cause trouble
anywhere...
A16652fd5d83c0473bd1e39d9a2117a6?d=identicon&s=25 Dirk Meijer (Guest)
on 2005-12-20 22:36
(Received via mailing list)
i've always used this:

0.upto(string.length-1) do |n|
    p string[n,1]
end

anything wrong with this?
greetings, Dirk.


2005/12/20, Florian GroÃ? <florgro@gmail.com>:
4b174722d1b1a4bbd9672e1ab50c30a9?d=identicon&s=25 Ryan Leavengood (Guest)
on 2005-12-20 23:00
(Received via mailing list)
"Wrong" is a strong word, but I'd say this isn't ideal Ruby for two
reasons:

1. Generally in Ruby internal iterators (i.e. each, each_byte, etc.)
are preferred over external iterators like what you have here (and for
and while loops.)
2. Your code isn't as efficient, though it wasn't as bad as I thought:

-------------------------------------------------------------------------
|                      QuickBench Session Started                       |
|                            300 Iterations                             |
-------------------------------------------------------------------------
                                  user     system      total        real
1. s.each_byte{|b| b.chr ...  2.656000   0.000000   2.656000 (
2.669000)
2. 0.upto(s.length-1) { |...  2.859000   0.000000   2.859000 (
2.887000)
3. s.split(//).each { |ch...  3.297000   0.000000   3.297000 (
3.290000)
4. s.scan(/./m) { |charac...  7.594000   0.156000   7.750000 (
7.776000)
-------------------------------------------------------------------------
|              Fastest was <1. s.each_byte{|b| b.chr ...>               |
-------------------------------------------------------------------------

The string s above was 4000 x characters.

I was quite surprised the scan was so much slower, especially compared
to split, which creates an array every time.

Ryan
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2005-12-20 23:06
(Received via mailing list)
On Dec 20, 2005, at 3:35 PM, Dirk Meijer wrote:

> i've always used this:
>
> 0.upto(string.length-1) do |n|
>     p string[n,1]
> end
>
> anything wrong with this?

You mean besides the fact that it's not very Rubyish?  <laughs>
Seriously, it seems fine, though I prefer each_byte() or scan(/./m).

James Edward Gray II
123320fdc17940dfc8e365edb48fbff2?d=identicon&s=25 Bob Showalter (Guest)
on 2005-12-20 23:12
(Received via mailing list)
shinya wrote:
> Hi there!
> I'm a ruby newbie, and I'm searching for a way to iterate every char in
> a string, but I cannot find any easy way. My problem is to look at every
> char in a string and match it with some known letter.

If you just want to know if a string contains a character:

    puts "Yep!" if str.include?("X")

> I use the String#each_byte iterator for now, but it still be a poor
> solution :/

Others have suggested various iterators, but why not use standard jcode
lib?

    require 'jcode'
    str.each_char { |c| puts c }
4b174722d1b1a4bbd9672e1ab50c30a9?d=identicon&s=25 Ryan Leavengood (Guest)
on 2005-12-20 23:27
(Received via mailing list)
On 12/20/05, Bob Showalter <bob_showalter@taylorwhite.com> wrote:
>
> Others have suggested various iterators, but why not use standard jcode lib?
>
>     require 'jcode'
>     str.each_char { |c| puts c }

In case anyone is curious, the above just uses scan(/./m), and is even
slower in my benchmark because of the extra method calls. But in
reality all are quite fast enough, and the performance differences
aren't all that significant.

Ryan
2dc2228d8db84b46bdd834b0515a26a1?d=identicon&s=25 Lyndon Samson (Guest)
on 2005-12-20 23:30
(Received via mailing list)
a="123"

0.upto(a.length) { |i| puts a[i..i] }
A7c9c275318af9e1e3812fab9660cd7c?d=identicon&s=25 Jeff Wood (Guest)
on 2005-12-20 23:36
(Received via mailing list)
a.split( // ).each { |c| puts c }

j.

On 12/20/05, Lyndon Samson <lyndon.samson@gmail.com> wrote:
> > char in a string and match it with some known letter.
> Into RFID? www.rfidnewsupdate.com Simple, fast, news.
>
>


--
"Remember. Understand. Believe. Yield! -> http://ruby-lang.org"

Jeff Wood
Af95bdaf87958c40150b813e94381bfd?d=identicon&s=25 Christer Nilsson (christer)
on 2005-12-21 00:32
>-------------------------------------------------------------------------
>|                      QuickBench Session Started                       |
>|                            300 Iterations                             |
>-------------------------------------------------------------------------
>                                  user     system      total        real
>1. s.each_byte{|b| b.chr ...  2.656000   0.000000   2.656000 (
>2.669000)

each_char should beat the current leader as b.chr is not needed.

Strange it is not a part of Ruby as the char is the most natural part of
a string.

Christer
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 unknown (Guest)
on 2005-12-21 00:49
(Received via mailing list)
On Dec 20, 2005, at 6:32 PM, Christer Nilsson wrote:
> Strange it is not a part of Ruby as the char is the most natural
> part of
> a string.

I don't think that is true.  The semantics of each_byte are quite clear
but exactly what is a character?  In some encodings
one byte is the same as one character but in other encodings it might
be two bytes or in others in might be a variable number of bytes.

Iterating by 'character' only has meaning with respect to a character
set
encoding and a Ruby string generally doesn't have that sort of
information.

I think it is has been said before but, a Ruby string is more like an
array of bytes than a sequence of code points in an (implicit)
character set.

Gary Wright
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-20 09:48
(Received via mailing list)
Lyndon Samson wrote:
> a="123"
>
> 0.upto(a.length) { |i| puts a[i..i] }

Alternatively:

a.length.times {|i| puts a[i].chr}

Many roads to Rome...

	robert
2a0f7bd2c54fbc44329d69555b96f1c5?d=identicon&s=25 Kev Jackson (Guest)
on 2006-03-20 10:09
(Received via mailing list)
Robert Klemme wrote:

>
> Many roads to Rome...
>
>     robert
>
or even

a.scan(/./) { |c| p c }

Kev
5befe95e6648daec3dd5728cd36602d0?d=identicon&s=25 Robert Klemme (Guest)
on 2006-03-20 10:43
(Received via mailing list)
Kev Jackson wrote:
>>
>> a.length.times {|i| puts a[i].chr}
>>
>> Many roads to Rome...
>>
>>     robert
>>
> or even
>
> a.scan(/./) { |c| p c }

We had that already: your version ignores newlines. :-)

	robert
2a0f7bd2c54fbc44329d69555b96f1c5?d=identicon&s=25 Kev Jackson (Guest)
on 2006-03-20 12:13
(Received via mailing list)
Robert Klemme wrote:

>>>
>>
>> a.scan(/./) { |c| p c }
>
>
> We had that already: your version ignores newlines. :-)
>
So it does!  Well I learnt something anyway :)

a = "ook\nook\tEeek!\n"
a.scan(/.|\s/) { |c| p c }
"o"
"o"
"k"
"\n"
"o"
"o"
"k"
"\t"
"E"
"e"
"e"
"k"
"!"
"\n"

(quick fix, and now handles tabs|spaces|new lines)

Kev
0b561a629b87f0bbf71b45ee5a48febb?d=identicon&s=25 Dave Burt (Guest)
on 2006-03-20 12:28
(Received via mailing list)
Kev Jackson wrote:
> a = "ook\nook\tEeek!\n"
> a.scan(/.|\s/) { |c| p c }

a.scan(/./m) {|c| p c }  # m is for multi-line

Cheers,
Dave
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-20 14:52
(Received via mailing list)
On Mar 20, 2006, at 3:38 AM, Robert Klemme wrote:

>>>
>>> a.length.times {|i| puts a[i].chr}
>>>
>>> Many roads to Rome...
>>>
>>>     robert
>>>
>> or even
>> a.scan(/./) { |c| p c }
>
> We had that already: your version ignores newlines. :-)

 >> require "jcode"
=> true
 >> "Hello\nWorld!".each_char { |chr| p chr }
"H"
"e"
"l"
"l"
"o"
"\n"
"W"
"o"
"r"
"l"
"d"
"!"
=> "Hello\nWorld!"

James Edward Gray II
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2006-03-20 17:29
(Received via mailing list)
Hello World

"I am puzzled".each_byte do |b| puts "%c" % b ;end



Cheers
Robert


On 3/20/06, James Edward Gray II <james@grayproductions.net> wrote:
> >>>
> >> a.scan(/./) { |c| p c }
> "o"
>
>


--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein
06db81f02537377c4bb207cdf8fd18ec?d=identicon&s=25 Mike Austin (Guest)
on 2006-03-20 20:38
(Received via mailing list)
"I am puzzled".each_byte { |b| puts b.chr }

I'm surprised that not many people knew about 'each_byte()'.  Maybe it's
a
problem with Ruby docs?  Or maybe it is just counter-intuitive - I would
expect
each() iterate over bytes, and provide each_lines() to iterate over
lines instead.

Mike

http://www.rubycentral.com/ref/
45196398e9685000d195ec626d477f0e?d=identicon&s=25 Trans (Guest)
on 2006-03-21 13:48
(Received via mailing list)
each_bytes is not a good way to do this, btw. It will not remain
compatibile with Ruby 2.0. And using enumerator is a pretty heavy
solution. Then there's this...

  require 'facet/string/chars'

Source code for chars.rb:

  class String

    # Returns an array of characters.
    #
    #   "abc".chars  #=> ["a","b","c"]
    #
    def chars
      self.split(//)
    end

  end

T.
This topic is locked and can not be replied to.