# Making a name like "Copy of...", "Copy 2 of..."

**URL:** <https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016>\
**Category:** Ruby\
**Created:** [May 28, 2009, 1:31pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016 "2009-05-28T13:31:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 1:31pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/1 "2009-05-28T13:31:55Z")

</div>

Here’s a little ruby exercise - i’m a bit brain damaged today and can’t  
think of a nice way to do this.

I want a method where you pass a name as a string and it returns ‘copy  
of x’ or ‘copy 2 of x’ eg

new\_name(“My Lesson”)  
=\> “Copy of My Lesson”

new\_name(“Copy of My Lesson”)  
=\> “Copy 2 of My Lesson”

new\_name(“Copy 10 of My Lesson”)  
=\> “Copy 11 of My Lesson”

I can only come up with horrible looking solutions but i feel there’s a  
nice way to do it. Anyone?

cheers  
max

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 1:45pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/2 "2009-05-28T13:45:35Z")

</div>

Max W. wrote:

> =\> “Copy 2 of My Lesson”
> 
> new\_name(“Copy 10 of My Lesson”)  
> =\> “Copy 11 of My Lesson”
> 
> I can only come up with horrible looking solutions but i feel there’s a  
> nice way to do it. Anyone?
> 
> cheers  
> max

Use a closure to keep track of how many copies you’ve made:

def copy(string)  
x = 0  
p = lambda do  
x += 1  
if x == 1  
“Copy of #{string}”  
else  
“Copy #{x} of #{string}”  
end  
end  
p  
end

c = copy(“My Lesson”)

puts c.call  
puts c.call  
puts c.call

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 3:02pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/3 "2009-05-28T15:02:00Z")

</div>

On Thu, May 28, 2009 at 8:04 AM, Max W.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > s = “My Lesson”  
> > > =\> “My Lesson”  
> > > copied\_name(_)  
> > > =\> “Copy of My Lesson”  
> > > copied\_name(_)  
> > > =\> “Copy 1 of My Lesson”  
> > > copied\_name(\_)  
> > > =\> “Copy 2 of My Lesson”

Well, taking that approach how about:

def copied\_name(source\_name)  
case source\_name  
when /^Copy of (._)$/i  
“Copy 1 of #{$1}”  
when /^Copy (\d+) of (._)$/i  
num = $1.to\_i  
“Copy #{num+1} of #{$2}”  
else  
“Copy of #{source\_name}”  
end  
end

s = “My Lesson” # =\> “My Lesson”  
s = copied\_name(s) # =\> “Copy of My Lesson”  
s = copied\_name(s) # =\> “Copy 1 of My Lesson”  
s = copied\_name(s) # =\> “Copy 2 of My Lesson”

However, since you used the i option on your regex maybe you wanted to  
preserve the case of the “Copy of part” which this doesn’t

s = “copy of My Lesson” # =\> “copy of My Lesson”  
s = copied\_name(s) # =\> “Copy 1 of My Lesson”  
s = copied\_name(s) # =\> “Copy 2 of My Lesson”  
s = copied\_name(s) # =\> “Copy 3 of My Lesson”

If so then this does:

def copied\_name(source\_name) # !\> method redefined; discarding old  
copied\_name  
case source\_name  
when /^(Copy )(of ._)$/i  
“#{$1}1 #{$2}”  
when /^(Copy )(\d+)( of ._)$/i  
num = $2.to\_i  
“#{$1}#{num+1}#{$3}”  
else  
“Copy of #{source\_name}”  
end  
end

s = “My Lesson” # =\> “My Lesson”  
s = copied\_name(s) # =\> “Copy of My Lesson”  
s = copied\_name(s) # =\> “Copy 1 of My Lesson”  
s = copied\_name(s) # =\> “Copy 2 of My Lesson”

s = “copy of My Lesson” # =\> “copy of My Lesson”  
s = copied\_name(s) # =\> “copy 1 of My Lesson”  
s = copied\_name(s) # =\> “copy 2 of My Lesson”  
s = copied\_name(s) # =\> “copy 3 of My Lesson”

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Twitter: [http://twitter.com/RickDeNatale](http://twitter.com/RickDeNatale)  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 3:12pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/4 "2009-05-28T15:12:17Z")

</div>

> def copied\_name(source\_name)  
> case source\_name  
> when /^Copy of (._)$/i  
> “Copy 1 of #{$1}”  
> when /^Copy (\d+) of (._)$/i  
> num = $1.to\_i  
> “Copy #{num+1} of #{$2}”  
> else  
> “Copy of #{source\_name}”  
> end  
> end

I’ll go with this one, thanks Rick!

max

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 2:04pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/5 "2009-05-28T14:04:41Z")

</div>

Tim H. wrote:

> Max W. wrote:
> 
> > =\> “Copy 2 of My Lesson”
> > 
> > new\_name(“Copy 10 of My Lesson”)  
> > =\> “Copy 11 of My Lesson”
> > 
> > I can only come up with horrible looking solutions but i feel there’s a  
> > nice way to do it. Anyone?
> > 
> > cheers  
> > max
> 
> Use a closure to keep track of how many copies you’ve made:
> 
> def copy(string)  
> x = 0  
> p = lambda do  
> x += 1  
> if x == 1  
> “Copy of #{string}”  
> else  
> “Copy #{x} of #{string}”  
> end  
> end  
> p  
> end
> 
> c = copy(“My Lesson”)
> 
> puts c.call  
> puts c.call  
> puts c.call

That method returns a proc though, rather than a string. Wouldn’t that  
mean that every time i want to call it i have to assign it to a variable  
and then call that variable? Or am i being dumb? here’s my  
hacky-feeling solution:

def copied\_name(source\_name)  
if source\_name.match /^Copy of/i  
new\_name = source\_name.gsub!(/^Copy of/i, “Copy 1 of”)  
elsif source\_name.match /^Copy \d+ of/i  
num = source\_name.scan(/\d+/).first.to\_i  
new\_name = source\_name.gsub!(/^Copy #{num} of/i, “Copy #{num+1}  
of”)  
else  
new\_name = "Copy of " + source\_name  
end  
end

> > s = “My Lesson”  
> > =\> “My Lesson”
> 
> > copied\_name(\_)  
> > =\> “Copy of My Lesson”
> 
> > copied\_name(\_)  
> > =\> “Copy 1 of My Lesson”
> 
> > copied\_name(\_)  
> > =\> “Copy 2 of My Lesson”

---

<div class="post-metadata">

**Author:** ![cmaxvv](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/85f322/32.png) [@cmaxvv](https://www.ruby-forum.com/u/cmaxvv)\
**Post date:** [May 28, 2009, 6:05pm UTC](https://www.ruby-forum.com/t/making-a-name-like-copy-of-copy-2-of/169016/6 "2009-05-28T18:05:43Z")

</div>

A bit more compact:

def copied\_name(source\_name)  
if source\_name =~ /\ACopy (\d+ )?of (.\*)\z/i  
“Copy #{($1||1).to\_i+1} of #{$2}”  
else  
“Copy of #{source\_name}”  
end  
end

You can simplify ($1||1) to just $1, if you don’t mind starting at Copy  
1 of… instead of Copy 2 of…
