问题如下:
一个长字符串: a_long_string = "a very long long string" 一个短字符串: short_string = "SHORT STRING"
要求:将短字符串,逐字符的循环
插入长字符串中。并返回修改后的长字符串。
例如:以上返回结果应该为:
aS HvOeRrTy SlToRnIgN GlSoHnOgR Ts tSrTiRnIgN
我自己先给一个实现: (脑子卡壳了,多谢二楼 pongyo 的提醒,汗~~~ )
很明显,我的实现绝对不是最 Rubyful 的。因为我没有很好的利用 Ruby 自身提供的 强大的字符串 API, 相信一定会有更好地解决方法。
下面是我的代码:
a_long_string = "a very long long string"
short_string = "SHORT STRING"
def insert_str(str1, str2)
tmp_str = ""
enum1 = str1.chars
index = 0
loop do
z = enum1.next << str2[index]
index = (index + 1) % str2.length
tmp_str << z
end
tmp_str
end
insert_str a_long_string, short_string
你把 print 语句换成把那个字符放到一个数组或者字符串里就行了呀。
def insert_str long, short
short_len = short.length
string_array = long.chars.enum_for(:inject, []).with_index do |(r, char), i|
r << char
r << short[i % short_len]
end
string_array.join
end
还有一个短版的
def insert_str l,s; l.split("").zip((s * (l.size / s.size) << s[0...(l.size % s.size)]).split("")).join;end
def merge_string(long, short)
result = []
long_size = long.size
i = 0
short.each_char do |char|
result << long[i]
result << char
i += 1
end
result.join('') << long[i..long_size]
end
我的思路很简单。
额 抛砖引玉。。
def insert_str long, short
short_arr = short.split("")
result = ""
long.split("").each{|str| result << str + short_arr.first and short_arr.rotate!}
return result
end
a_long_string = "a very long long string"
short_string = "SHORT STRING"
def insert_str(str1, str2)
ls, ss = [str1, str2].map(&:chars)
ls.zip(ss.cycle).join
end
def insert_str(long, short)
div, mod = long.size.divmod(short.size)
c = short * div + short[0..(mod - 1)]
long.chars.zip(c.chars).join
end
来个性能最差版
def insert_str(s1,s2)
s1.chars.zip((s2*(s1.length/s2.length+1)).chars).join
end
这个可能要好点
def insert_str2(s1,s2)
s1.chars.inject('') {|ss,s| ss << s + s2[(ss.length/2)%s2.length]}
end
我认为易读的版本
def insert(long,short)
enum_l = long.each_char
enum_s = short.each_char.cycle
temp = ""
loop do
temp << enum_l.next << enum_s.next
end
long.replace(temp)
end
我用手机上网,没法运行代码验证,不过我怀疑楼上用 zip 再 join 的方式能成功吗?zip 以后得到的数组,其元素也是一个数组,如 [['a','S'],[' ','H'], ...] 这样。这不可以直接 join 吧,还得 flatten 一下才行。
我觉得 map 那句是多余呀 ,修改一下 @hysios 的:-)
def insert_str(str1, str2)
str1.chars.zip(str2.chars.cycle).join
end
@hooopo 实际上我之前看错了需求 原始语句是这样的
def insert_str(str1, str2)
short, long = [str1, str2].sort.map(&:chars)
...
end
zip + cycle 真是经典,过瘾看着。
我也来个,不用 enumerator 的
def insert_str(str1, str2) i = -1 str1.split(//).join("\0").gsub("\0") do i = (i + 1) % str2.length str2[i] end end
不好意思,忘用代码风格了
def insert_str(str1, str2)
i = -1
str1.split(//).join("\0").gsub("\0") do
p $&
i = (i + 1) % str2.length
str2[i]
end
end
def insert_cycle_char long, short
long.split('').zip(short.split('').cycle).flatten.join
end
insert_cycle_char "a very long long string" , "SHORT STRING"
#28 楼 @geekontheway 这个比 @hysios 的差一些:chars 比 split 的语义更清晰,而且很可能性能更好,flatten 在 join 之前用是多余的
呃……来一个思路简单版的 把字串看成数组 两个两个往结果里加……
def insert_str2(str1,str2)
result = ''
str1.length.times {|n|result << str1[n] << str2[n % str2.length] }
result
end
在来复杂地,纯属恶搞了,别介意。
递归版的
def insert_str(long, short, index = 0)
long[index] ? long[index] << short[index % short.length] << insert_str(long, short, index + 1)
: ""
end
fiber 版的:
def insert_str(long, short)
require 'fiber'
longer = Fiber.new do |shorter, result|
long.each_char do |char|
result << char
shorter.transfer(longer, result)
end
result
end
shorter = Fiber.new do |longer, result|
short.each_char.cycle do |char|
result << char
longer.transfer(shorter, result)
end
end
longer.transfer(shorter, "")
end
笨办法 容易看懂 哈 嘿嘿
a_long_string = "a very long long string"
short_string = "SHORT STRING"
result=""
i = 0
a_long_string.each_char do |a|
i=0 if i == short_string.length
result << a << short_string[i]
i += 1
end
result