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
On Thu, Aug 14, 2008 at 11:21:10PM +0900, Lorenzo E. Danielsson wrote:
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 9:21 AM, Lorenzo E. Danielsson
[email protected] wrote:
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
On Thu, 2008-08-14 at 23:40 +0900, Gregory S. wrote:
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:52 +0900, Michael L. wrote:
rem
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 Aug 14, 2008, at 8:21 AM, Lorenzo E. Danielsson wrote:
what is a decent way of performing this?
Lorenzo
don’t do it by index
string.tr! chars, ‘’
a @ http://codeforpeople.com/
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.
On Aug 14, 9:21 am, “Lorenzo E. Danielsson”
[email protected] wrote:
as does 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.
On Fri, 2008-08-15 at 11:56 +0900, David M. wrote:
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
2008/8/14 Lorenzo E. Danielsson [email protected]:
On Thu, 2008-08-14 at 23:52 +0900, Michael L. wrote:
On Thu, Aug 14, 2008 at 9:21 AM, Lorenzo E. Danielsson
Whereas I would have wanted:
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
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 R. (“apeiros”)
Lorenzo E. Danielsson wrote:
as does 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