Idiom of removing a particular character from a String?

  • Thread starter Lorenzo E. Danielsson
  • Start date
L

Lorenzo E. Danielsson

Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?

Lorenzo
 
G

Gregory Seidman

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?


str[index..index] = ""
--Greg
 
M

Michael Libby

Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?


irb(main):022:0> rem = "foobar"
=> "foobar"
irb(main):023:0> rem.slice!(3).chr
=> "b"
irb(main):024:0> rem
=> "fooar"

-Michael
 
L

Lorenzo E. Danielsson

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?


str[index..index] = ""


So:
str = "hello"
rem = str.clone
rem[2,1] = "" # => "helo"
rem

Sorry, but that doesn't look any cleaner than my solution. I was looking
for something like:

class String
def delete_at(i)
str = self.clone
str = ""
end
end

str = "hello"
rem = str.delete_at(2) # => "helo"

That is, original string does not get tampered with. Resulting string is
original string minus exactly one character, at the specified index.

The above works, but I was hoping to avoid that by using some neat
idiom. This is not really a problem, but 99.x % of the time, Ruby does
things in a way that are so cool that I tend to get lazy and expect it
to always behave that way. The few times it doesn't, it comes as a
shock.
 
L

Lorenzo E. Danielsson

Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?


irb(main):022:0> rem = "foobar"
=> "foobar"
irb(main):023:0> rem.slice!(3).chr
=> "b"
irb(main):024:0> rem
=> "fooar"


The "problem" is that slice does not return the resulting string but
rather the sliced portion. This is of course not a problem in itself, it
is rather the expected behavior of slice. But, in my particular case
that *still* leads to:

str = "hello"
rem = str.clone
rem.slice!(2)
rem # => "helo"

Whereas I would have wanted:

str = "hello"
rem = str.slice_and_return_everything_but_the_sliced_part(2)

This is partly a matter of laziness on my part, that I prefer to type
two lines instead of four. But, it is also a matter that it kind of
breaks the POLS, at least for me. I have grown accustomed to being able
to perform:

result = original.some_method(args)

and have the result be some mutilated form of original, with original
being left intact. So when String#delete_at(index) doesn't work, it
feels like it *should* have worked..

Anyways, nothing worth losing sleep over..
 
A

ara.t.howard

Hi all,

Is there any particular idiom for removing a particular character
from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?

Lorenzo


don't do it by index

string.tr! chars, ''



a @ http://codeforpeople.com/
 
Y

Yossef Mendelssohn

Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem =3D str.clone
rem =3D ""
rem

as does this:

rem =3D str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?

Lorenzo


Lorenzo,

It seems reading comprehension isn't a strong suit for ruby-talk
today.

As far as I know, there is no such method. You're probably stuck with
reopening String and adding it yourself.
 
D

David Masover

So:
str = "hello"
rem = str.clone
rem[2,1] = "" # => "helo"
rem

For what it's worth, I've been using Object#tap (1.8.7 or higher) in
situations like these:

str = "hello"
str.clone.tap { |rem|
rem[2,1] = ''
}

Ordinarily, I wouldn't mention it, but you were asking for idiomatic things,
and I like that idiom.
 
R

Robert Klemme

The "problem" is that slice does not return the resulting string but
rather the sliced portion. This is of course not a problem in itself, it
is rather the expected behavior of slice. But, in my particular case
that *still* leads to:

str = "hello"
rem = str.clone
rem.slice!(2)
rem # => "helo"

Whereas I would have wanted:

str = "hello"
rem = str.slice_and_return_everything_but_the_sliced_part(2)

This is partly a matter of laziness on my part, that I prefer to type
two lines instead of four. But, it is also a matter that it kind of
breaks the POLS, at least for me. I have grown accustomed to being able
to perform:

result = original.some_method(args)

and have the result be some mutilated form of original, with original
being left intact. So when String#delete_at(index) doesn't work, it
feels like it *should* have worked..

Anyways, nothing worth losing sleep over..

If you want to do it on one line you could do this:

irb(main):011:0> s = "abcdef"
=> "abcdef"
irb(main):012:0> 5.times {|i| puts s.sub /\A(.{#{i}})./, '\\1' }
bcdef
acdef
abdef
abcef
abcdf
=> 5
irb(main):013:0>

Granted, it's not too idiomatic...

Kind regards

robert
 
L

Lorenzo E. Danielsson

So:
str = "hello"
rem = str.clone
rem[2,1] = "" # => "helo"
rem

For what it's worth, I've been using Object#tap (1.8.7 or higher) in
situations like these:

str = "hello"
str.clone.tap { |rem|
rem[2,1] = ''
}

Ordinarily, I wouldn't mention it, but you were asking for idiomatic things,
and I like that idiom.

Agreed, Object#tap looks very nice. Thanks for the info.

Lorenzo
 
S

Stefan Rusterholz

Lorenzo said:
Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string?

str[0...index]+str[index+1..-1]

NB: this won't delete the char from str but only return a new string
without the character at index.

regards
Stefan Rusterholz ("apeiros")
 
M

Michael Morin

Lorenzo said:
Hi all,

Is there any particular idiom for removing a particular character from a
string *by index* and returning the resulting string? The following
makes my old eyes sore:

rem = str.clone
rem = ""
rem

as does this:

rem = str.scan(/./)
rem.delete_at(i)
rem.to_s

It seems there should be some more idiomatic way to do this, something
like str.annihilate_char_at_index_possibly_without_a_bang(i), read as
String#delete_at(i) and String#delete_at!(i). Of course these methods
don't exist, and "".methods doesn't turn up anything interesting. So
what is a *decent* way of performing this?

Lorenzo


There have been some good solutions posted already. However, I don't
think I'd want to be repeating them many times (or at all) in my code.
Whichever solution you use, it's probably best to hide it away in the
String class somewhere, else your code will suddenly start looking...
perl-like.

This seems sensible to me. If you're on 1.8.7 or 1.9 (I am not), you
can also use the tap method.

class String
def rem(idx)
c = clone
c[idx..idx] = ""
c
end

def rem!(idx)
self[idx..idx] = ""
self
end
end

If you're on 1.8.7, 1.9 or feel like implementing it yourself, you can
use the tap method. Using the tap method seems cleaner.

unless Object.methods.include? "tap"
class Object
def tap
yield self
self
end
end
end

class String
def rem(idx)
clone.tap {|t| t[idx..idx] = "" }
end

def rem!(idx)
tap {|t| t[idx..idx] = "" }
end
end

--
Michael Morin
Guide to Ruby
http://ruby.about.com/
Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top