模式计算器蟒蛇



我的一个朋友向我展示了他在面试中遇到的一个有趣的问题。所以你有一个像 n = 3413289830 这样的数字和一个像 p = a-bcdefghij 这样的模式,你需要创建一个函数来接受这个输入和输出 -413289827。显然,它应该适用于加法和减法的数字和字母的任何组合。我制定了这段代码,但我很确定它可以改进,因为我认为它有点低效。

pattern = 'a-bcdefghij'       
n = '3413289830'
lst = []
def splitnb(n, pattern):
save = dict()
if(len(n) != len(pattern) - 1):
print('Pattern needs to match number')
else:
if( '-' in pattern):
patlst = pattern.split('-')
elif('+' in pattern):
patlst = pattern.split('+')
for char in n:
a = list(n)
for pat in patlst:
first  = patlst[0].split()
rest = pat.split()
for l in first[0]:
f1 = l
lst.append(f1)
for l2 in rest[0]:
f2 = l2
lst.append(f2)
save = dict(zip(lst, a))
nb = ''
if( '-' in pattern):
for i in first[0]:
numb = int(save.get(i))
for j in rest[0]:
nb += save.get(j)
numb1 = numb - int(nb)
elif('+' in pattern):
for i in first[0]:
numb = int(save.get(i))
for j in rest[0]:
nb += save.get(j)
numb1 = numb + int(nb)
return numb1
f1 = splitnb(n, pattern)
f2 = splitnb('1234', 'ab+cd')
f3 = splitnb('22', 'a-b')

一种方法是采用模式并将每个字符替换为应该存在的数字,然后eval结果

string.ascii_letters是按字母顺序排列的所有 ASCII 字符的字符串,以小写开头。这可用于将字符转换为应从n中提取的数字的索引

>>> [n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern]
['3', '-', '4', '1', '3', '2', '8', '9', '8', '3', '0']

我们添加if x in string.ascii_letters else x以便运算符不被转换。然后,加入结果列表以获取字符串

>>> ''.join(n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern)
'3-413289830'

删除括号会将列表理解转换为应该稍微提高性能的生成器。然后,您可以使用eval运行此字符串,就好像它是python代码一样

>>> eval(''.join(n[string.ascii_letters.index(x)] if x in string.ascii_letters else x for x in pattern))
-413289827

仅当您信任给定的输入时,才应使用 eval,因为它可以执行任意代码

可以使用正则表达式拆分和zip_longest使其变得小而干净,如下所示

import re
from itertools import zip_longest
pattern = 'a-bcdefghij'       
n = '3413289830'
lst = re.split("[^a-z]", pattern)
oprs = [None] + re.findall("[^a-z]", pattern)
result = 0
for x, opr in zip_longest(lst, oprs):
op = int(n[:len(x)])
n = n[len(x):]
if opr == "-":
op = -op
result+=op

result

你想

  • 确定应应用的操作
  • 找到拆分的位置
  • 使用拆分的各个部分作为操作数应用操作

一种方法可能是遍历模式以查找操作数及其在列表中的位置(这也是拆分的位置(,然后将运算符与执行所需操作的运算符模块中的函数匹配。 如果不允许使用运算符模块,则可以编写自己的函数。

import operator
operators = { 
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
}
# operator not allowed?  Then '+': def add(a, b):return a + b etc.
def splitnb(n, pattern):
if len(n) != len(pattern) - 1:
print("Pattern needs to match number")
return
# Find the operator and its position.
for _i, op in enumerate(pattern):
if not op.isalpha():
break
# Lookup the operator and execute it.
return operators[op](int(n[:_i]), int(n[_i:]))

如果允许pattern不包含运算符,或者运算符可能位于数字字符串的开头或结尾,则需要为这些情况添加一些验证。

最新更新