Idiom of removing a particular character from a String?

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[i] = ""
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

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[i] = ""
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] = ""

Lorenzo

--Greg

···

On Thu, Aug 14, 2008 at 11:21:10PM +0900, Lorenzo E. Danielsson wrote:

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

-Michael

···

On Thu, Aug 14, 2008 at 9:21 AM, Lorenzo E. Danielsson <danielsson.lorenzo@gmail.com> wrote:

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[i] = ""
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?

don't do it by index

   string.tr! chars, ''

a @ http://codeforpeople.com/

···

On Aug 14, 2008, at 8:21 AM, Lorenzo E. Danielsson wrote:

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[i] = ""
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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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.

···

On Aug 14, 9:21 am, "Lorenzo E. Danielsson" <danielsson.lore...@gmail.com> wrote:

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[i] = ""
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

--
-yossef

Lorenzo E. Danielsson wrote:

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")

···

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

Lorenzo E. Danielsson wrote:

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[i] = ""
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

Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company

> 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[i] = ""
> 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[i] = ""
  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.

···

On Thu, 2008-08-14 at 23:40 +0900, Gregory Seidman wrote:

On Thu, Aug 14, 2008 at 11:21:10PM +0900, Lorenzo E. Danielsson wrote:

> Lorenzo
--Greg

> 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[i] = ""
> 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..

···

On Thu, 2008-08-14 at 23:52 +0900, Michael Libby wrote:

On Thu, Aug 14, 2008 at 9:21 AM, Lorenzo E. Danielsson > <danielsson.lorenzo@gmail.com> wrote:

-Michael

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.

···

On Thursday 14 August 2008 11:59:51 Lorenzo E. Danielsson wrote:

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

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

···

2008/8/14 Lorenzo E. Danielsson <danielsson.lorenzo@gmail.com>:

On Thu, 2008-08-14 at 23:52 +0900, Michael Libby wrote:

On Thu, Aug 14, 2008 at 9:21 AM, Lorenzo E. Danielsson

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..

--
use.inject do |as, often| as.you_can - without end

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

Lorenzo

···

On Fri, 2008-08-15 at 11:56 +0900, David Masover wrote:

On Thursday 14 August 2008 11:59:51 Lorenzo E. Danielsson wrote:

> 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.