2011-08-29 17 views
0

我對追蹤號碼做了一個校驗位的方法如下,但它只是感覺冗長/馬虎。它可以重構,只是通常清理?這個校驗數字方法可以重構嗎?

我正在運行Ruby 1.8.7。

def is_fedex(number) 
    n = number.reverse[0..14] 

    check_digit = n.first.to_i 

    even_numbers = n[1..1].to_i + n[3..3].to_i + n[5..5].to_i + n[7..7].to_i + n[9..9].to_i + n[11..11].to_i + n[13..13].to_i 

    even_numbers = even_numbers * 3 

    odd_numbers = n[2..2].to_i + n[4..4].to_i + n[6..6].to_i + n[8..8].to_i + n[10..10].to_i + n[12..12].to_i + n[14..14].to_i 

    total = even_numbers + odd_numbers 

    multiple_of_ten = total + 10 - (total % 10) 

    remainder = multiple_of_ten - total 

    if remainder == check_digit 
    true 
    else 
    false 
    end 
end 

編輯:以下是有效和無效的數字。

有效期:9612019950078574025848

無效:9612019950078574025847

+1

布爾表達式已經評估爲「true」或「false」,所以不是最後的「if」,你可以執行「remainder == check_digit」。 –

+0

你有沒有一個有效和無效號碼的例子?這允許在發佈之前回答的人測試他們的代碼。 – Martijn

回答

2
def is_fedex(number) 
    total = (7..20).inject(0) {|sum, i| sum + number[i..i].to_i * (i.odd? ? 1 : 3) } 
    number[-1].to_i == (total/10.0).ceil * 10 - total 
end 

我相信你應該保留你的代碼。雖然這不是慣用的或聰明的,但是從現在開始幾個月之後,你將會毫無困難地理解它。

1

我不是一個紅寶石程序員,所以如果有任何語法是關閉的,我很抱歉,但你應該得到的總體思路。我看到的一些事情:首先,您不需要對數組進行切片,單個索引就足夠了。其次,你可以做這樣的事情:

total = 0 
for i in (1..14) 
    total += n[i].to_i * (i % 2 == 1 ? 1 : 3) 
end 

第三,其餘的可以簡化爲10 - (總共%10)。

+0

你可以使用'i.odd?'而不是'i%2 == 1' –

0

試試這個:

#assuming number comes in as a string 
def is_fedex(number) 
    n = number.reverse[0..14].scan(/./) 
    check_digit = n[0].to_i 
    total = 0 
    n[1..14].each_with_index {|d,i| total += d.to_i * (i.even? ? 3 : 1) } 
    check_digit == 10 - (total % 10) 
end 

> is_fedex("123456789") => true 

編輯結合凱文建議

0

像這樣簡化的其餘邏輯是什麼?

def is_fedex(number) 
    even_arr, odd_arr = number.to_s[1..13].split(//).map(&:to_i).partition.with_index { |n, i| i.even? } 
    total = even_arr.inject(:+) * 3 + odd_arr.inject(:+) 

    number.to_s.reverse[0..0].to_i == (total + 10 - (total % 10)) - total 
end 

如果你能給我一個有效和無效的號碼,我可以測試它的工作原理,也許進一步調整它:)

+0

上帝,我愛Enumerable:D – Martijn

+0

有效期:9612019950078574025848和無效:9612019950078574025847 – Shpigford

+0

是enumerable有各種各樣有趣的技巧...雖然我認爲你可能已經超出了自己試圖分開偶數和奇數出來...而是你可以循環,並通過一次數學計算。 :) – DGM

0

這個功能應該到:

def is_fedex(number) 
    # sanity check 
    return false unless number.length == 15 

    data = number[0..13].reverse 
    check_digit = number[14..14].to_i 

    total = (0..data.length-1).inject(0) do |total, i| 
    total += data[i..i].to_i * 3**((i+1)%2) 
    end 

    (10 - total % 10) == check_digit 
end 

算術表達式3**((i+1)%2)可能看起來有點複雜,但基本上與(i.odd? ? 1 : 3)相同。兩種變體是正確的,你用的是取決於你(和可能會影響速度......)

另外要注意的是,如果你使用Ruby 1.9,你可以使用data[i]代替這是需要對Ruby 1.8 data[i..i]

1

我知道你正在運行1.8.7,但這裏的使用each_slice我的企圖,並注入中聯,一個1.9.2特點:

def is_fedex(number) 
    total = number.reverse[1..14].split(//).map(&:to_i).each_slice(2).inject(0) do |t, (e,o)| 
    t += e*3 + o 
    end 
    10 - (total % 10) == number[-1].to_i 
end 

它通過這兩個試驗

+0

噢,不錯,我不知道你可以使用'each_with_index'和'inject' –

+0

使用each_slice(2)而不是each_with_index,你可以處理奇數和偶數索引的數字對,這樣就不需要重複測試。 – steenslag

相關問題