【问题标题】:Converting Float to String without Truncating leading or trailing zeros将浮点数转换为字符串而不截断前导零或尾随零
【发布时间】:2015-02-08 21:25:25
【问题描述】:

我正在尝试从 Excel 电子表格中提取邮政编码并将它们作为字符串加载到列表中。

import xlrd
BIL = xlrd.open_workbook(r"C:\Temp\Stores.xls)    
Worksheet = BIL.sheet_by_name("Open_Locations")
ZIPs = []
for record in Worksheet.col(17):
    if record.value == "Zip":
        pass
    else:
        ZIPs.append(record.value)

不幸的是,这个 Excel 工作簿是由其他人管理的,所以我不能简单地将 Excel 电子表格中包含邮政编码的字段转换为文本来解决我的问题。此外,不管你信不信,这个 Excel 电子表格也被一些商业智能系统使用。因此,将该字段从数字更改为字符串可能会导致利用此工作簿的其他工作流出现问题,我不知道。

我发现,当我按原样打印数字而不先转换为整数或字符串时,我当然会得到一堆浮点数。我预料到了,因为 Excel 将数字存储为浮点数。

>>>Zips
[u'06405',
 04650.0,
 10017.0,
 71055.0,
 70801.0]

我没想到的是,当我将这些浮点数转换为 int 以摆脱十进制值时,然后将其结果转换为字符串,结果是任何作为邮政编码一部分的前导或尾随零值被截断。

import xlrd
BIL = xlrd.open_workbook(r"C:\Temp\Stores.xls)    
Worksheet = BIL.sheet_by_name("Open_Locations")
ZIPs = []
for record in Worksheet.col(17):
    if record.value == "Zip":
        pass
    else:
        ZIPs.append(str(int(record.value)))

>>>Zips
['6405',
 '465',
 '10017',
 '71055',
 '70801']

如何将这些邮政编码转换为字符串而不丢弃前导零或尾随零,或者在截断之前确定值上的前导零和尾随零的数量并酌情附加它们?

【问题讨论】:

    标签: string xlrd zipcode floating-point-conversion


    【解决方案1】:

    所有邮政编码(不包括 Zip+4)都是 5 个字符,因此您可以填充为 5:

    C#

    Python:

    【讨论】:

    • 谢谢艾尔。 rjust() 会将任何零添加到 zip 的开头,将 06405 的 zip 截断为 6405 的 zip 转换回 06405。但是,如果前导零和尾随零都被截断,例如 04650 截断为 465 的邮政编码,使用 rjust() 将返回值 00465,与原始 zip 完全不同的结果。关键似乎是确定 zip 中有多少前导零或尾随零,然后酌情在两端填充零。我已经修改了问题的 zip 示例以反映这一点
    【解决方案2】:

    所以经过一番修修补补,原来答案是:

    1. 不要将邮政编码转换为 int,因为这也会截断任何 前导零
    2. 将字符串显式编码为 utf-8

    unicode 字符串指示符的存在提示我,当它出现在某些值上时,这可能是答案,但在我打印列表时不是全部

    for record in Worksheet.col(17):
        if record.value == "Zip":
            pass
        else:
            # In this case, the value is still being returned as float, because                          
            it has 1 significant digit of 0 appended to the end. So we'll cast 
            as string and explicitly encode it as utf-8 which will retain the 
            leading and trailing zeros of the value and also truncate the 
            significant digits via index.
            if len(str(record.value).encode('utf-8')) > 5 
                ZIPs.append(str(record.value).encode('utf-8'))
            else:
                # In this case, the value is already being returned as a unicode 
                string for some reason, probably because of poor excel worksheet 
                management, but in any case cast as string and explicitly encode 
                as utf-8 just for peace of mind.
                ZIPs.append(str(record.value).encode('utf-8'))
    
    >>>Zips
       ['06405',
        '04650',
        '10017',
        '71055',
        '70801']
    

    如果有人有更优雅的方法,我很想看看。

    【讨论】:

      【解决方案3】:

      您可以尝试通过字符串操作来做到这一点。

      我们在这里的假设是该列将是邮政编码,因此末尾的“.0”永远是不必要的。

      以下内容将出现在您的 else 语句中:

      record_str = str(record.value)
      formatted_record = record_str[:-2] if record_str.endswith('.0') else record_str
      ZIPs.append(formatted_record )
      

      或者,如果您想冒险,我们在这里的假设是阅读此列将始终具有“.0”,否则可能会导致意外行为。

      ZIPs.append(str(record.value)[:-2])
      

      【讨论】:

        猜你喜欢
        • 2022-09-29
        • 2019-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-03
        • 1970-01-01
        • 2014-08-09
        相关资源
        最近更新 更多