在Python中,根据它们的性质将字符串转换为浮点数或整数。

3

在解析文件后,我获得了一个包含数字值的字符串列表,比如:

my_list = ['1', '-2.356', '00.57', '0', '-1', '02678', '0.005367', '0', '1']

为了获得这些数字值,我执行以下步骤:
new_list = [float(i) for i in my_list] . 

问题在于整数值 - 这些值在我处理的文件中占据了大多数 - 也被转换为浮点数,因此占用更多的内存 - 更不用说其他问题(我必须使用其中一些作为索引 - 因此它们需要在某个时候转换为整数..)
有没有一种有效的方法只将需要的字符串转换为浮点数(我不能失去任何精度),并将所有其它的值都转换为整数?

1
你可以查看字符串是否包含 '.',然后决定你想要使用 float(i) 还是 int(i)。那么像 1.0 这样可以被表示为整数的浮点数怎么办? - jonrsharpe
请参见 https://dev59.com/wXRC5IYBdhLWcg3wMeDf - PM 2Ring
2个回答

4

您可以编写一个函数,将字符串转换为整数(如果可能)或浮点数(如果不是整数),如果连这都不行,就将它们保留为字符串。

my_list = ['1', '-2.356', '00.57', '0', '-1', '02678', '0.005367', '0', '1']

def converter(n):
  try:
    return int(n)
  except ValueError:
    try:
      return float(n)
    except ValueError:
      return n  # <- left as string

print([converter(x) for x in my_list])  # -> [1, -2.356, 0.57, 0, -1, 2678, 0.005367, 0, 1]

这是因为int('2.3')int(2.3)不同。前者返回一个错误,而后者裁剪浮点数并返回2
此外需要注意的是try块的排列顺序非常重要,因为float('2')是可以正常工作的。因此,首先尝试将其转换为int

1
如果 intfloat 失败,你也要处理字符串,那么可以返回 +one - akash karothiya
我本来想将这个问题标记为重复,但是我找不到一个好的目标来优先考虑这种技术,我同意这是最好的方法,除非你能保证所有的字符串都是简单的,即没有像“12E3”或“Nan”这样的字符串。 - PM 2Ring
  • 一是要看到问题并不简单,提出一个好的解决方案。
- Reblochon Masque

2
您列表中的int和float之间的区别在于是否有 . ,您可以使用它来选择要使用的强制转换。
new_list = [float(elt) if '.' in elt else int(elt) for elt in my_list] 

编辑:

为了处理浮点数的特殊情况,@EvKounis提出的转换函数是一个好主意;在@PM2Ring的评论后,进一步扩展它:

my_list = ['1', '1E3', '-inf', 'inf', 'NaN', 'nan', '-2.356', '00.57', '0', '-1', '02678', '0.005367', '0', '1', '398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857']

def convert_to_int_or_float(elt):
    try:
        e = float(elt)
    except ValueError:
        raise ValueError
    elt = elt.lower()
    if '.' in elt or 'e' in elt or 'inf' in elt or 'nan' in elt:
        pass
    else:
        e = int(elt)
    return e

[convert_to_int_or_float(e) for e in my_list]

输出:

[1,
 1000.0,
 -inf,
 inf,
 nan,
 nan,
 -2.356,
 0.57,
 0,
 -1,
 2678,
 0.005367,
 0,
 1,
 398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857398472398472943657410843104729572471308172374018301478744723974523987452938729847194719841471476574572394710481048075434810482398752481038185739847239847294365741084310472957247130817237401830147874472397452398745293872984719471984147147657457239471048104807543481048239875248103818573984723984729436574108431047295724713081723740183014787447239745239874529387298471947198414714765745723947104810480754348104823987524810381857]

希望楼主的数据不包含没有小数点的科学计数法浮点数,例如“12E3”。 - PM 2Ring
现在它处理NaN-infinf和科学计数法,感谢您的要求更多。 - Reblochon Masque
现在,具有大于浮点数最大值的值的整数也被正确处理。 - Reblochon Masque
Ev. Kounis的技术可以处理所有“有趣”的浮点数,而无需进行特定测试。但是,您仍然可以简化这些测试。例如:elt = elt.lower() if any(u in elt for u in ('.', 'e', 'inf', 'nan')): pass - PM 2Ring
确实是这样。当我用你的任意(语句)替换case by case测试时,对于非常大的整数,代码会崩溃:它返回float('inf')。我不知道为什么,但我已经在屏幕前呆了太久,现在无法深入研究它。 - Reblochon Masque
奇怪。如果elt表示一个非常大的整数,那么e = float(elt)将成功,并返回float('inf'),就像你说的那样。但是e = int(elt)也应该被执行,在我的机器上(运行Python 3.6.0),使用你的if测试或我的版本都是这样。 - PM 2Ring

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