我必须制作一个为数字添加逗号的方法。我不能在方法中使用正则表达式。经过大量的修补和研究后,我发现了这个解决方案:
def separate_comma(number)
c = { :value => "", :length => 0 }
r = number.to_s.reverse.split("").inject(c) do |t, e|
iv, il = t[:value], t[:length]
iv += ',' if il % 3 == 0 && il != 0
{ :value => iv + e, :length => il + 1 }
end
r[:value].reverse!
end
有人可以帮助我解释每行的语法吗?这里有很多事情,我很难掌握所有这些。此外,任何关于如何重构它并使其更优雅的想法 - 不使用正则表达式。谢谢你们
答案 0 :(得分:2)
def separate_comma(number)
c = { :value => "", :length => 0 }
c是一个散列,其中:value =“”和length = 0(稍后将使用)
r = number.to_s.reverse.split("").
将数字转换为字符串,反转并拆分为数字。示例:
19874 --> ["4","7","8","9","1"]
.inject(c) do |t, e|
Inject“通过应用二进制操作组合枚举的所有元素,由块或命名方法或运算符的符号指定”
它使用当前数组项转换“备忘录”,从而生成用于下一个数组项的新备忘录。
http://ruby-doc.org/core-2.2.1/Enumerable.html#method-i-inject
在这种情况下,每个数组项都将修改'c'哈希
iv, il = t[:value], t[:length]
iv最初等于c:值,il等于c:length
iv += ',' if il % 3 == 0 && il != 0
如果当前计数是三的倍数,这将在当前数组项之前添加一个逗号(我的例子,这只适用于第四个数组项(稍后会清楚)
{ :value => iv + e, :length => il + 1 }
(可能已修改的)数组项附加到t [:value]哈希中的字符串中,并且:length增加1
end
完成我的例子
<强> 1 强>
iv = ""
il = 0
e = "4"
returns { :value "4", :length 1}
<强> 2 强>
iv = "4"
il = 1
e = "7"
returns { :value "47", :length 2}
第3 强>
iv = "47"
il = 2
e = "8"
returns { :value "478":, :length 3}
<强> 4 强>
iv = "478"
il = 3
e = "9," (the if statement returns true and so a comma is appended to the 9)
returns { :value "478,9", :length 4}
<强> 5 强>
iv = "478,9"
il = 4
e = 1
returns { :value "478,91", :length 5}
(这是由inject语句返回的)
r[:value].reverse!
获取inject语句返回的值并反转它的字符。 “19,874” 端
在使代码更易于理解方面,您可以使用这些更具描述性的变量名称:
c = number_hash_memo
r = result
t = number_hash
e = char
iv = hash_val
il = hash_length
答案 1 :(得分:1)
<强> c = { :value => "", :length => 0 }
强>
c是一个包含两个密钥对的哈希,第一个密钥是value
一个空字符串,第二个密钥是length
,它是0.
此行的用途是用于创建输入到inject方法中的对象的初始状态。
<强> number.to_s.reverse.split("")
强>
将以相反的顺序返回'number'数组,例如:
number = 12345
number.to_s.reverse.split("")
=> ["5", "4", "3", "2", "1"]
<强> r = number.to_s.reverse.split("").inject(c) do |t, e|
强>
在ruby社区中,可枚举#injection是一种奇特的方法。它采用哈希和块。对象的初始状态是您在inject方法中输入的hash
。 |t,e|
中的't'是由注入块中最后一行代码的返回值设置的对象,其初始状态是输入到注入方法的哈希。 |t,e|
中的'e'是您要迭代的数组中的元素。
<强> iv, il = t[:value], t[:length]
强>
这些是您在每次迭代中设置的值。
<强> iv += ',' if il % 3 == 0 && il != 0
强>
在长度为3且不为0的条件下添加逗号。因此,在每三次迭代后,会在您的值对象中添加一个逗号。
<强> { :value => iv + e, :length => il + 1 }
强>
Enumerable#inject方法中最后一行的返回值传递给't'对象。
<强> r[:value].reverse!
强>
代码块将返回't'。 然后最终将值反转回其原始状态并返回。
答案 2 :(得分:0)
您发布的内容有效,但这是一个非常低效的解决方案。而不是重构它,最好只重写它:
def separate_comma(number)
digits = number.to_s.reverse.split('')
buffer = []
buffer << digits.shift(3).join until digits.empty?
buffer.join(',').reverse
end
这也应该更容易理解。
答案 3 :(得分:0)
这会更容易
def comma_seperate(number)
s = number.to_s.reverse.split(//).each_slice(3).to_a
i = 0
while i<s.length-1
s[i].push(",")
i+=1
end
s.join().reverse
end