我一直在尝试编码练习,以掩盖除了输入的最后四位数或字符之外的所有数字。
我认为我的解决方案有效但看起来有点笨拙。有没有人有关于如何重构它的想法?
这是我的代码:
def mask(string)
z = string.to_s.length
if z <= 4
return string
elsif z > 4
array = []
string1 = string.to_s.chars
string1[0..((z-1)-4)].each do |s|
array << "#"
end
array << string1[(z-4)..(z-1)]
puts array.join(", ").delete(", ").inspect
end
end
答案 0 :(得分:7)
positive lookahead让它变得非常简单。如果任何字符后跟至少4个字符,则会被替换:
"654321".gsub(/.(?=.{4})/,'#')
# "##4321"
以下是正则表达式的描述:
r = /
. # Just one character
(?= # which must be followed by
.{4} # 4 characters
) #
/x # free-spacing mode, allows comments inside regex
请注意,正则表达式一次只匹配一个字符,即使每次匹配最多需要检查5个字符:
"654321".scan(r)
# => ["6", "5"]
/(.)..../
不起作用,因为每次迭代会消耗5个字符:
"654321".scan(/(.)..../)
# => [["6"]]
"abcdefghij".scan(/(.)..../)
# => [["a"], ["f"]]
如果要参数化未屏蔽字符串的长度,可以使用variable interpolation:
all_but = 4
/.(?=.{#{all_but}})/
# => /.(?=.{4})/
将其打包成一个方法,它变为:
def mask(string, all_but = 4, char = '#')
string.gsub(/.(?=.{#{all_but}})/, char)
end
p mask('testabcdef')
# '######cdef'
p mask('1234')
# '1234'
p mask('123')
# '123'
p mask('x')
# 'x'
您也可以将其改为句子:
def mask(string, all_but = 4, char = '#')
string.gsub(/\w(?=\w{#{all_but}})/, char)
end
p mask('It even works for multiple words')
# "It even #orks for ####iple #ords"
在编程中命名是非常重要的,特别是在动态语言中。
string.to_s
如果string
确实是一个字符串,则没有任何理由可以调用to_s
。
如果string
不是字符串,您应该在to_s
之前致电gsub
,但也应该将string
重命名为更好的说明:
object.to_s
array.to_s
whatever.to_s
puts array.join(", ").delete(", ").inspect
你想做什么?您可以使用join
:
[1,2,[3,4]].join(", ").delete(", ")
# "1234"
[1,2,[3,4]].join
# "1234"
请注意.delete(", ")
以任何顺序删除每个逗号和每个空格。它不仅删除", "
子串:
",a b,,, cc".delete(', ')
# "abcc"
["1,2", "3,4"].join(', ').delete(', ')
# "1234"
答案 1 :(得分:3)
Ruby使得这类事情变得非常简单:
class String
def asteriskify(tail = 4, char = '#')
if (length <= tail)
self
else
char * (length - tail) + self[-tail, tail]
end
end
end
然后你可以像这样申请:
"moo".asteriskify
# => "moo"
"testing".asteriskify
# => "###ting"
"password".asteriskify(5, '*')
# => "***sword"
答案 2 :(得分:2)
试试这个
def mask(string)
string[0..-5] = '#' * (string.length - 4)
string
end
mask("12345678")
=> "####5678"
答案 3 :(得分:1)
我也会在此主题中添加我的解决方案:)
def mask(str)
str.match(/(.*)(.{4})/)
'#' * ($1 || '').size + ($2 || str)
end
mask('abcdef') # => "##cdef"
mask('x') # => "x"
答案 4 :(得分:1)
我提供此解决方案主要是为了提醒读者https://docs.microsoft.com/en-us/azure/application-insights/app-insights-asp-net-dependencies没有块返回枚举器。
def mask(str, nbr_unmasked, mask_char)
str.gsub(/./).with_index { |s,i| i < str.size-nbr_unmasked ? mask_char : s }
end
mask("abcdef", 4, '#')
#=> "##cdef"
mask("abcdef", 99, '#')
#=> "######"
答案 5 :(得分:0)
尝试使用tap
def mask_string(str)
str.tap { |p| p[0...-4] = '#' * (p[0...-4].length) } if str.length > 4
str
end
mask_string('ABCDEF') # => ##CDEF
mask_string('AA') # => AA
mask_string('S') # => 'S'