2017-11-11 132 views
1
import numpy as np 

def validation(x): 
    x = np.asarray(x) 
    if len(x) != 16: 
     return("Card doesn't have exactly 16 digits. Try again") 
    values = [] 
    rwhat = x[::-1] # reverse the order of the credit card numbers 
    rwhat 

    checkDig = rwhat[0] # the leftmost [originally rightmost] digit which is the checkDigit ... I'm just doing this because it's easier for me to work with 
    checkDig 
    withCheck = [] # to append later when we add all single digits 

    everySec = rwhat[1:16:2] # we don't want to double the checkDigit, but we're extracting every second digit starting from the first, leftmost digit [tho we omit this checkDigit 
    everySec 

    def double(num): # to double the extracted second digit values 
     return [j * 2 for j in everySec] 
    xx = double(everySec) 
    xx 

    def getSingle(y): # to add the sum of the digits of any of the new doubled numbers which happen to be greater than 9 
     u = 0 
     while y: 
      u += y % 10 
      y //= 10 
     return u 
    yy=list(map(getSingle,xx)) 
    yy 
    withCheck.append(checkDig) 
    withCheck 
    new_vv = withCheck + yy 
    new_vv # now we include the omitted checkDigit into this new list which should all be single digits 

    sumDig = sum(new_vv) 
    sumDig # now have the sum of the the new_vv list. 

    def final(f): 
     if sumDig % 10 == 0: # if the calculated sum is divisible by 10, then the card is valid. 
      return("Valid") 
     else: 
      return("Invalid") 
    go = final(sumDig) 
    values.append(go) # basically just appending into values[] for the sake of the validation(x) function, and so we can return something for this function. in this case we'd return values as seen below. 
    return values 

所以我創建了這個程序,我需要弄清楚如何定義第一個(最外層)函數的參數將卡號作爲一個由16列組成的多維數組,並最終返回一個列表的值表示「有效」或「無效」。將參數(x)指定爲具有特定列數的多維數組?

def validation(x)工作內的東西,我已經在實際製作上述函數之前測試過它,但我只是不知道如何指定這個函數[也就是這個程序基本上是]在一個多維數組中16列。

我敢肯定的代碼行關於if len(x) != 16是問題的一部分,但它的工作原理,如果我們只是想運行一個卡[16個位數又名一組]

例如,如果我想嘗試validation(([[0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5],[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]])我與輸出困擾:"Card doesn't have exactly 16 digits. Try again",而不是正常運行,並返回我,指出在各自有效還是無效的列表,以每張卡

+0

修復您的縮進。這是Python無效的表現。 –

+0

如果您想使用numpy,請使用numpy。不要使用像'len'這樣的東西,它按順序給出了行數,而不是列數和列表解析。 –

+0

當您修復了代碼格式時,請對我進行平郵,然後我會給您寫回答。 –

回答

0

您需要檢查shape程序。事情是這樣的:

assert len(x.shape) == 2, "input must be 2D" 
assert x.shape[1] == 16, "input must have 16 columns" 
assert np.issubdtype(x.dtype, np.integer), "input must be integers" 
+0

您能否解釋第一行以及「輸入必須是20」的含義? – zainy

+0

「Two Dee」不是「二十」。第一行檢查輸入是否有兩個維度,例如, 1D或3D等 –

+0

哦對不起大聲笑。是的,這是有道理的。所以我將它添加到我的代碼中,擺脫了我原來的len內容,但是當我現在運行程序時,我最後在我的原始文章中提到過,我得到'AttributeError:'list'object has no屬性「shape」# – zainy

2

除了基本的問題解決在@ JohnZwinck的答案,還有就是你不使用numpy的數組作爲numpy的陣列的基本事實。

對於您正在編寫的程序,不應該有任何明確的循環或解釋來計算總和或其他數量。 Numpy數組是用於向量化代碼並簡化其外觀的優秀工具。

這裏有一些改變我除了建議斷言數組的大小:

  • 斷言,所有的數字都在範圍0-9:

    assert np.all((x >= 0) & (x <= 9)) 
    
  • 請注意您是使用行還是使用列。如果您有n行,每行16列,checkDig應該是x[:, 0],這是第一列,而不是x[0],這是第一行,相當於x[0, :]

  • 無需反轉陣列:checkDig只是最後一個元素:x[:, -1]; everySec變成x[:, 1:-1:2]。考慮到它的使用方式,沒有必要對其進行逆轉。
  • 功能double僅僅是一個爛攤子:

    1. 聲明一個未使用的參數num
    2. 你然後everySec運行在封閉命名空間
    3. 您應用列表理解到numpy的陣列,這是比較慢,很難理解,並不會爲二維數組正常工作。

    你可以只用xx = everySec * 2取代它,甚至擺脫xx,只是做everySec *= 2

  • getSingle是矯枉過正。你的數字是九倍以下,所以結果不能超過兩位數(總和不能超過九位)。 yy = (xx // 10) + (xx % 10)應該做得很好。通過維護numpy數組而不是列表,您可以使所有操作適用於2D數組,而不必遍歷列表中的所有單個元素。
  • 您操作的其餘都有點不清楚。您似乎正在執行Luhn algorithm,但沒有嘗試添加非加倍數字。非加倍數字x[:, :-1:2]
  • 中調用內建sum將阻止你沒有一個循環處理多個輸入。使用np.sumaxis=1對每行中的列進行求和。
  • values.append(go)只調用一次。如果你想處理多個數字,你將不得不編寫某種循環。讓go成爲布爾數組而不是單個布爾值會容易得多。

結合所有這些建議得到這樣的:

def validation(x): 
    x = np.asanyarray(x) 
    assert x.ndim == 2, "input must be 2D" 
    assert x.shape[1] == 16, "input must have 16 columns" 
    assert np.issubdtype(x.dtype, np.integer), "input must be integers" 
    assert np.all((x >= 0) & (x <= 9)) 
    checkDig = x[:, -1] 
    xx = x[:, 1:-1:2] * 2 
    yy = x[:, :-1:2] 
    sumDig = np.sum(xx, axis=1) + np.sum(yy, axis=1) + checkDig 
    return ['Invalid' if s % 10 else 'Valid' for s in sumDig] 

功能可以通過將輸入的副本以避免覆蓋東西,就地操作進一步簡化:

def validation(x): 
    x = np.array(x, copy=True, subok=True) 
    assert x.ndim == 2, "input must be 2D" 
    assert x.shape[1] == 16, "input must have 16 columns" 
    assert np.issubdtype(x.dtype, np.integer), "input must be integers" 
    assert np.all((x >= 0) & (x <= 9)) 
    y = x[1:-1:2] 
    x[1:-1:2] = ((2 * y) // 10) + ((2 * y) % 10) 
    sumDig = np.sum(x, axis=1) 
    return ['Invalid' if s % 10 else 'Valid' for s in sumDig] 
相關問題