从字符串中删除一个字符,然后使用字典进行键匹配

4

我想写一个函数,使用map和reduce将字符串转换为浮点数(这里不使用int())。以下是我目前的代码:

from functools import reduce

def str2float(s):
    def char2number(s):
        s = s.replace('.', '')
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] #here i try to get pure numbers 

    def find_digt(s):
        return (len(s) - s.find('.') - 1) if ',' in s else 0

    return reduce(lambda x, y: (10 * x + y), (map(char2number, s))) / pow(10, find_digt(s))


print(str2float('1456.124'))

所以在这之后,我遇到了一个错误:
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[sn]  # [s] is the [key]
KeyError: ''

这意味着“''”不在字典中。我进行了一些测试,例如:
s = '1234.456'
s = s.replace(',', '')
print('' in s) #True

所以现在的问题是,一旦
s = s.replace('.', '')

把 '.' 替换成 '' 后,它并没有清除字符串中的 '.'。

我想知道这里发生了什么。由于字符串是不可变的,那么正确的清除字符串中的字符的方法是什么?


你有意地检查了s中是否包含逗号,但是却搜索了句点的索引吗?看起来这是你在使用另一个分隔符时留下的痕迹。但这绝对很奇怪。 - MSeifert
1
它应该是“。”! - Luke P
3个回答

1
我添加了一个微不足道的跟踪语句:
def char2number(s):
    print ("ENTER", s)
    s = s.replace('.', '')
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

输出:

ENTER 1
ENTER 4
ENTER 5
ENTER 6
ENTER .
Traceback (most recent call last):
  File "so.py", line 15, in <module>
    print(str2float('1456.124'))
  File "so.py", line 12, in str2float
    return reduce(lambda x, y: (10 * x + y), (map(char2number, s))) / pow(10, find_digt(s))
  File "so.py", line 7, in char2number
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] #here i try to get pure numbers 
KeyError: ''

你将'1234.456'的单个字符传递给char2number。当你传递点时,替换确实清除它,留下一个空字符串。
我不确定你的意图如何。你的代码似乎期望将整个字符串发送到支持函数。然而,map作用于可迭代元素的序列。
至于更改字符串,你不能真正地这样做:你已经做了我们可以做的事情,将replace的输出分配回原始字符串。你遇到的问题只是它在你代码中的某一点上作用于单个字符。

1
问题在于您使用map迭代未更改的输入字符串,因为您仅在char2number函数中删除了.。在函数之外,替换没有发生。
我建议立即找到位置并进行替换:
from functools import reduce

def str2float(s):
    pos_decimal_point = (len(s) - s.find('.') - 1) if '.' in s else 0
    s = s.replace('.', '')

    def char2number(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] #here i try to get pure numbers 

    return reduce(lambda x, y: (10 * x + y), 
                  (map(char2number, s))) / pow(10, pos_decimal_point)


print(str2float('1456.124'))

1
您的想法是正确的,只需在将s传递给map函数之前替换其中的.即可:
map(char2number, s.replace('.',''))

注意:find_digt()函数中有一个错别字,应该改为:if '.' in s...
如果你还想处理逗号,可以添加额外的replace函数来去除它们:
stripped_s = s.replace('.','').replace(',','')
return reduce(lambda x, y: (10 * x + y), (map(char2number, stripped_s))) / pow(10, find_digt(s))

print(str2float('1,456.124'))
1456.124

完整代码:

def str2float(s):
    def char2number(s):
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]  

    def find_digt(s):
        return (len(s) - s.find('.') - 1) if '.' in s else 0

    stripped_s = s.replace('.','').replace(',','')
    return reduce(lambda x, y: (10 * x + y), (map(char2number, stripped_s))) / pow(10, find_digt(s))

    print(str2float('1,456.124'))
    1456.124

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接