2017-11-11 133 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] 
相关问题