Return number of spaces at the beginning of a line

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

On Tue, Mar 30, 2010 at 3:41 AM, Jesse B. [email protected] wrote:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

Posted via http://www.ruby-forum.com/.

You could use regex you could also, if the data is a string or an array,
split them into a char array

e.g. :
s = " hello"
s = s.chars.to_a
=> [" ", " ", " ", " ", “h”, “e”, “l”, “l”, “o”]

s.each do | c |
if( c == " " )
i = i+1
puts i
end
end

and that’ll count the number of spaces.

On Tue, Mar 30, 2010 at 11:41 AM, Jesse B. [email protected] wrote:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

If I understand your question correctly,

str = " hello"
p str =~ /\S/

Harry

On Mar 29, 2010, at 7:41 PM, Jesse B. wrote:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

Posted via http://www.ruby-forum.com/.

s = " abc"
s.index(%r{\S}) # => 3

s.scan(%r{^\s*}).first.size # => 3

Gennady.

On Mar 29, 9:35 pm, Steve H. [email protected] wrote:

def num_leading_spaces(s)
  prefix = (s =~ /(\s*)/)
  $1.length
end

puts num_leading_spaces('   hello')

Oops, still not sure whether this is ideal, but this is better than my
other version:

def num_leading_spaces(s)
  s =~ /(\s*)/
  $1.length
end

2010/3/30 Jesse B. [email protected]:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

spaces = str[/\A\s*/].length

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

I’d rather use the approach above because it always works (i.e. even
with empty strings). Your approach could be done like this:

spaces = /\S/ =~ s

as has been show already. But this fails for empty strings.

Kind regards

robert

On Mar 29, 7:41 pm, “Jesse B.” [email protected] wrote:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

I think the following expresses what you are trying to do, but I do
not know if this is the most efficient or idiomatic way to do it:

def num_leading_spaces(s)
  prefix = (s =~ /(\s*)/)
  $1.length
end

puts num_leading_spaces('   hello')

Two things:

  1. The name of the method multi_line_spaces won’t actually test, because
    TestUnit only considers a method to be a test if it begins with ‘test’
    so
    you should change it’s name to test_multi_line_spaces

  2. I thought of another test you should add. Throwing wholly bad data at
    it.
    In this case, nil
    def test_nil
    assert_raises NoMethodError do
    leading_spaces nil
    end
    end

‘The Pragmatic Programmer’ says that it is better to crash early, so I
tested that it should throw an error.

You might also consider what you would like it to do in the event that
you
pass it something not a string. Perhaps invoke the to_s method and then
get
the length of the leading whitespace. Perhaps raise a different error.

On Mon, Mar 29, 2010 at 8:41 PM, Jesse B. [email protected] wrote:

How would I find the number of spaces at the beginning of a line before
the occurrance of the first non-space character?

Would the best method be to use a regular expression that covers all
non-space characters and get the index of the first occurrance of that?

Posted via http://www.ruby-forum.com/.

Hi, a quick appraisal of the issues with previous solutions.

This solution counts non-leading spaces
i = 0
" hello ".chars.to_a.each do |c|
i+=1 if( c == " " )
end

This one returns nil if there is not text after the leading whitespaces.
str =~ /\S/

Each of these count non-space whitespaces (ie " \t hello" would be 3
instead
of 1 )
s.index(%r{\S})

str[/\A\s*/].length

s =~ /(\s*)/
$1.length

So here is a quick suite you can use to test the solutions, along with a
solution which passes. If this suite doesn’t accurately reflect what you
were trying to do, modify it and re-post :slight_smile: You’ll be a lot more likely
to
get a solution which does explicitly what you are looking for, and maybe
find some areas that are ambiguous in your question, such as multi-line
strings, and strings with mixtures of whitespace types.

require ‘test/unit’

def leading_spaces( str )

fill this out however you like, my solution is:

str =~ /[^ ]/ || str.length
end

class TestLeadingSpaces < Test::Unit::TestCase

def test_one_space
assert_equal 1 , leading_spaces(’ ')
end

def test_empty_string
assert_equal 0 , leading_spaces(‘’)
end

def test_two_leading_spaces
assert_equal 2 , leading_spaces(’ hello’)
end

def test_no_spaces
assert_equal 0 , leading_spaces(‘hello’)
end

def test_spaces_inside_but_not_leading
assert_equal 0 , leading_spaces(‘hello there’)
end

def test_spaces_inside_and_leading
assert_equal 2 , leading_spaces(’ hello there’)
end

def test_trailing_spaces_not_leading
assert_equal 0 , leading_spaces('hello ')
end

def test_trailing_spaces_and_inside
assert_equal 0 , leading_spaces('hello there ')
end

def test_spaces_everywhere
assert_equal 1 , leading_spaces(’ hello there ')
end

def test_mixture_of_spaces_and_tabs
assert_equal 1 , leading_spaces(" \t hello")
end

the following are not really defined in the question, this is what I

think the OP is asking for

might also be asking for an array listing the indentions for each

line?
def multi_line_spaces
assert_equal 6 , leading_spaces(<<-MULTI_LINE_STRING)
this is six spaces
this is eight
MULTI_LINE_STRING
end
end

This second post with the “spaces only” fix seems to meet all the needs
of what I was looking for.

I love that this got 9 replies in the middle of the night.
thanks everyone for your help.

Robert K. wrote:

2010/3/30 Josh C. [email protected]:

On Mon, Mar 29, 2010 at 8:41 PM, Jesse B. [email protected] wrote:

Hi, a quick appraisal of the issues with previous solutions.

Each of these count non-space whitespaces (ie " \t hello" would be 3 instead
of 1 )
s.index(%r{\S})

str[/\A\s*/].length

s =~ /(\s*)/
$1.length

Oh, that’s easily fixed: just replace \s with ’ ’ e.g. s[\A */].length
(still my favorite). I thought general whitespace was sought after.

Kind regards

robert

2010/3/30 Josh C. [email protected]:

On Mon, Mar 29, 2010 at 8:41 PM, Jesse B. [email protected] wrote:

Hi, a quick appraisal of the issues with previous solutions.

Each of these count non-space whitespaces (ie " \t hello" would be 3 instead
of 1 )
s.index(%r{\S})

str[/\A\s*/].length

s =~ /(\s*)/
$1.length

Oh, that’s easily fixed: just replace \s with ’ ’ e.g. s[\A */].length
(still my favorite). I thought general whitespace was sought after.

Kind regards

robert

I love that this got 9 replies in the middle of the night.
thanks everyone for your help.

What do you mean, middle of the night? It’s quite sunny here and the
sun isn’t even going to settle soon. :wink:

One Bright Day In The Middle Of The Night. :slight_smile:

Harry

2010/3/30 Jesse B. [email protected]:

This second post with the “spaces only” fix seems to meet all the needs
of what I was looking for.

I love that this got 9 replies in the middle of the night.
thanks everyone for your help.

What do you mean, middle of the night? It’s quite sunny here and the
sun isn’t even going to settle soon. :wink:

Cheers

robert

On Tue, Mar 30, 2010 at 2:18 PM, Robert K.
[email protected] wrote:

robert
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Well, it’s also nowhere near the middle of the night here
(n*100 kilometres west of Robert?, where 0 < n < 13?)
but it’s definitely not “quite sunny”! In fact, it’s raining!
(To quote from “A Song of the Weather”
by Flanders and Swann - 1950s/1960s sort of English Tom Lehrer’s:
April brings the sweet spring showers.
On and on for hours and hours.)

How about this? I think it’s different from the other solutions(?),
it seems to work, and it doesn’t create a string object(?).
(str =~ /[^ ]/) || str.length

def q( str )
ns = str =~ /[^ ]/ || str.length # actual code
spaces = str[/\A */].length # Robert’s 2nd post
str.inspect.ljust(10) + " #=> " + ns.inspect + " =?= " +
spaces.inspect
end

“” #=> 0 =?= 0
" " #=> 1 =?= 1
" " #=> 2 =?= 2
“c” #=> 0 =?= 0
" c" #=> 1 =?= 1
" c" #=> 2 =?= 2
" \t cc" #=> 1 =?= 1

2010/3/30 Colin B. [email protected]:

sun isn’t even going to settle soon. :wink:

Well, it’s also nowhere near the middle of the night here
(n*100 kilometres west of Robert?, where 0 < n < 13?)

Yeah, that sounds about right.

but it’s definitely not “quite sunny”! In fact, it’s raining!
(To quote from “A Song of the Weather”
by Flanders and Swann - 1950s/1960s sort of English Tom Lehrer’s:
April brings the sweet spring showers.
On and on for hours and hours.)

I think I have to hurry: rain radar indicates showers coming my way.

How about this? I think it’s different from the other solutions(?),
it seems to work, and it doesn’t create a string object(?).
(str =~ /[^ ]/) || str.length

I’m afraid, that is not correct; the String is created as a side
effect and stored in a global variable:

irb(main):001:0> str = " foo"
=> " foo"
irb(main):002:0> str =~ /[^ ]/
=> 3
irb(main):003:0> $&
=> “f”

And it has the disadvantage over str[/\A */].length that likely is
slower because of the alternative.

Kind regards

robert

On 03/30/2010 06:22 PM, Colin B. wrote:

On Tue, Mar 30, 2010 at 4:35 PM, Robert K.
[email protected] wrote:

I think I have to hurry: rain radar indicates showers coming my way.
From the west?

From south west.

And it has the disadvantage over str[/\A */].length that likely is
slower because of the alternative.

I’m glad that my (mathematically trained!) caution decided to add that “(?)”.
I nearly didn’t put it in, but had second thoughts!
I’d forgotten about the global variables.
I see that str.index( regexp ) also sets $&, which is nice to be reminded of,
first because it might come in handy, and second because, as you point out,
side effects might make what appears to be an “elegant” solution not elegant.
Well, one learns from ones mistakes!

Absolutely! And there is still so much around to learn… I am still
waiting for a bit of spare time to invest in having a closer look at
PostgreSql…

Kind regards

robert

I’m impressed.

Comment: It seems amazing that even as languages get more and more
powerful, we seem to spend more time pushing strings through hoops.

I’ve been using ‘?’ and ‘!’ on the end of some methods - NOW I’m
appending things to the method names to break ties. I am converting
from sym to s, remove the /?!/ and so on and I’m rather on strange
ground exactly where my app is the most prone to serious performance
degradation. So this has been on my mind some…

Then, following this thought I just read up on “Fancy” (shhh!) (while
reading up on new Wiki features) and was thinking about if there might
a way to use some of that for really “core” stuff.

I’m really happy with Ruby performance so far, but it could be a
factor coming up, and it seems to be a ok idea to keep an eye out for
ways to tweak performance?

Any comments on converting Symbols to Strings, doing things on them,
then converting back - is there some better way?

Adding a ‘+’ method to Kernel for symbols would reduce code clutter
but still ultimately end up requiring conversion from symbols to
strings to do
the append operation, right?

(ruby 1.9 is allowing me to do more with the ?! chars than I think I
remember 1.8 where I think I remember getting some errors around
this. )

I would not normally care much, or feel a particular need to
understand what is going on under the hood, but I have a performance
issue right here and this happens be one of the things I’m working on.

comments?

then, what would be the best form to add two symbols together (ending
up with a symbol again)

quick check:
sym1, sym2= :abc_defg?, sym2 = :xyz
puts (sym1 + sym2).to_s
=> ‘: undefined method `+’ for :abc_defg?:Symbol (NoMethodError)

On Tue, Mar 30, 2010 at 4:35 PM, Robert K.
[email protected] wrote:

I think I have to hurry: rain radar indicates showers coming my way.
From the west?

irb(main):003:0> $& #=> “f”

And it has the disadvantage over str[/\A */].length that likely is
slower because of the alternative.

I’m glad that my (mathematically trained!) caution decided to add that
“(?)”.
I nearly didn’t put it in, but had second thoughts!
I’d forgotten about the global variables.
I see that str.index( regexp ) also sets $&, which is nice to be
reminded of,
first because it might come in handy, and second because, as you point
out,
side effects might make what appears to be an “elegant” solution not
elegant.
Well, one learns from ones mistakes!

On Mar 31, 7:19 am, Aldric G. [email protected] wrote:

I would not normally care much, or feel a particular need to
Do you expect this code to work?

I think you’re using symbols inappropriately. What -are- you doing with
them? If you need to add two names together, then my guess is, just
stick with strings.

Posted viahttp://www.ruby-forum.com/.

just quickly: they start life as a method name so i was hoping they
could stay symbols - but i need a tie breaker for the one level key
that becomes a simpleton method (name) in this “whiteboard” class. i
keep trying to use all symbols. note: ruby is not fighting me with
the /?!/ - so the door seems open to bite the bullet and convert →
append → reconvert but it “hurts” my sense of symmetry - but thanks -
that makes perfect sense (and now that i think about it- it had to be
that way, almost).

thunk