Ruby - 有人可以向我解释这段代码的每一行

时间:2015-04-11 21:35:35

标签: ruby

我必须制作一个为数字添加逗号的方法。我不能在方法中使用正则表达式。经过大量的修补和研究后,我发现了这个解决方案:

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

有人可以帮助我解释每行的语法吗?这里有很多事情,我很难掌握所有这些。此外,任何关于如何重构它并使其更优雅的想法 - 不使用正则表达式。谢谢你们

4 个答案:

答案 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)

这会更容易

  1. 取数字(例如:number =&gt; 12345678)
  2. 将其转换为字符串(“12345678”)
  3. 反转它(“87654321”)
  4. 将其转换为数组([“8”,“7”,“6”,“5”,“4”,“3”,“2”,“1”])
  5. 尝试制作带有3个元素的子数组#最后一个将包含余数([[“8”,“7”,“6”],[“5”,“4”,“3”],[“2 “,”1“]])
  6. 遍历子数组以将逗号推送到子数组的最后位置,除了最后一个
  7. 连接数组以制作字符串
  8. 反转字符串
  9. here is the code我写过

    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