【问题标题】:Convert string (without any separator) to list将字符串(不带任何分隔符)转换为列表
【发布时间】:2013-03-09 17:51:51
【问题描述】:

我有一个电话号码(字符串),例如“+123-456-7890”,我想变成一个看起来像这样的列表:[+, 1, 2, 3, -, ...., 0]。

为什么?所以我可以遍历列表并删除所有符号,所以我只剩下一个数字列表,然后我可以将其转换回字符串。

解决此问题的最佳方法是什么?我遇到的所有解决方案都不适用,因为我在数字之间没有任何特殊字符(所以我不能在那里拆分字符串。)

有什么想法吗?我真的很感激!

编辑 - 这是我尝试过的:

x = row.translate(None, string.digits)
list = x.split()

还有:

filter(lambda x: x isdigit())

【问题讨论】:

  • 顺便说一句——通常,我们希望用户展示他们已经尝试过的代码。这是一个非常简单的问题,因此查看您尝试过的(以及失败的)可能会帮助我们帮助您更好地理解语言(而不是仅仅给您一个答案并让您在没有真正工具的情况下解决问题)下一个问题)
  • 好的 - 我已经添加了我尝试过的内容。我认为它不相关,所以我最初没有发布它
  • 这正是我所要求的。我已将我的反对票改为赞成票,因为这些尝试似乎是合理的。
  • @nv39 所以你正在弄清楚更喜欢哪种解决方案。 mgilson、uptownnickbrown、tur1ng 和 Kabie 有可行的解决方案。我的偏好是使用生成器 + 连接的 mgilson; Kabie 用于连接加过滤器(更喜欢生成器而不是过滤器); tur1ng 用于正则表达式(不是很复杂,不足以保证正则表达式); uptownnickbrown 用于迭代和字符串追加(有效但不是首选的 python 习语)。无论如何,这就是我看待它们的方式——纯粹是风格问题。我怀疑这里是否有任何速度问题需要考虑。
  • @nv39,顺便说一句,row.translate(None, '+-') 似乎是最快的

标签: python string list


【解决方案1】:

制作一个列表(your_string)

>>> s = "mep"
>>> list(s)
['m', 'e', 'p']

【讨论】:

    【解决方案2】:

    你的意思是你想要这样的东西:

    ''.join(n for n in phone_str if n.isdigit())
    

    这利用了字符串可迭代的事实。当您迭代它们时,它们一次产生 1 个字符。


    关于你的努力,

    这个实际上删除字符串中的所有数字,只留下非数字。

    x = row.translate(None, string.digits)
    

    这个是在空白处分割字符串,而不是在每个字符之后:

    list = x.split()
    

    【讨论】:

    • 第一个不起作用,我得到了字符串而不是 python 列表。是否缺少 []?
    • 我正在解决“然后我可以将其转换回字符串”。 OP问题的一部分。如果你只想要一个 0-9 的数字列表,你可以这样做:[n for n in phone_str if n.isdigit()] 或类似的东西(取决于你想要一个字符列表还是 int 列表)。
    【解决方案3】:
    ''.join(filter(str.isdigit, "+123-456-7890"))
    

    【讨论】:

    • 感谢您的回答 - 它有效!这里有一些答案,所以我试图找出最好的方法是什么。你能告诉我这种方式是否/为什么比tur1ng给出的答案更好吗?谢谢!!
    【解决方案4】:

    你可以使用 re 模块:

    import re
    re.sub(r'\D', '', '+123-456-7890')
    

    这会将所有非数字替换为 ''。

    【讨论】:

    • 感谢您的回答 - 效果很好。你能告诉我为什么这个答案比 mgilson 给出的更好吗?他们都工作......我试图找出哪个更好/为什么
    • 可能比生成器快,但我对此表示怀疑。您也可以通过使用列表理解来加速生成器解决方案,但这并不是特别“pythonic”。最终,我更喜欢 list-comp/generator 因为任何人都可以阅读它。即使您不知道有一个str.isdigit 函数,您也可能猜到它是如何工作的。有了这个,你的读者至少需要一个基本的正则表达式知识,这不是你可以假设的。
    • @mgilson 毫无疑问regex 的神秘本质。最终的问题是“哪个更好?”实际上无法回答。解决方案不同。
    • 如果你编译正则表达式会快一点。经过测试。
    • @Kabie -- 比什么更快?比以前更快还是比其他解决方案更快?另外,你是怎么测试的?
    【解决方案5】:

    我知道这个问题已经得到解答,但只是指出timeit 对解决方案效率的看法。使用这些参数:

    size = 30
    s = [str(random.randint(0, 9)) for i in range(size)] + (size/3) * ['-']
    random.shuffle(s)
    s = ''.join(['+'] + s)
    timec = 1000
    

    即“电话号码”有30位数字,1个加sing和10个'-'。我已经测试了这些方法:

    def justdigits(s):
        justdigitsres = ""
        for char in s:
            if char.isdigit():
                justdigitsres += str(char)
        return justdigitsres
    
    re_compiled = re.compile(r'\D')
    
    print('Filter: %ss' % timeit.Timer(lambda : ''.join(filter(str.isdigit, s))).timeit(timec))
    print('GE: %ss' % timeit.Timer(lambda : ''.join(n for n in s if n.isdigit())).timeit(timec))
    print('LC: %ss' % timeit.Timer(lambda : ''.join([n for n in s if n.isdigit()])).timeit(timec))
    print('For loop: %ss' % timeit.Timer(lambda : justdigits(s)).timeit(timec))
    print('RE: %ss' % timeit.Timer(lambda : re.sub(r'\D', '', s)).timeit(timec))
    print('REC: %ss' % timeit.Timer(lambda : re_compiled.sub('', s)).timeit(timec))
    print('Translate: %ss' % timeit.Timer(lambda : s.translate(None, '+-')).timeit(timec))
    

    并得出以下结果:

    Filter: 0.0145790576935s
    GE: 0.0185861587524s
    LC: 0.0151798725128s
    For loop: 0.0242128372192s
    RE: 0.0120108127594s
    REC: 0.00868797302246s
    Translate: 0.00118899345398s
    

    显然 GE 和 LC 仍然比正则表达式或已编译的正则表达式慢。显然我的 CPython 2.6.6 并没有优化字符串添加。 translate 似乎是最快的(这是意料之中的,因为问题被表述为“忽略这两个符号”,而不是“获取这些数字”,我认为这是相当低级的)。

    对于size = 100

    Filter: 0.0357120037079s
    GE: 0.0465779304504s
    LC: 0.0428011417389s
    For loop: 0.0733139514923s
    RE: 0.0213229656219s
    REC: 0.0103371143341s
    Translate: 0.000978946685791s
    

    对于size = 1000

    Filter: 0.212141036987s
    GE: 0.198996067047s
    LC: 0.196880102158s
    For loop: 0.365696907043s
    RE: 0.0880808830261s
    REC: 0.086804151535s
    Translate: 0.00587010383606s
    

    【讨论】:

    • 请注意,正则表达式仅在第一次编译。在所有其他时间,re 将使用缓存版本,因此您只有额外的字典查找。绝大多数时间差异可能是因为第一次编译。
    • @mgilson 你的意思是RE 测试?我已经用timeit 的一次迭代和一个相当大的字符串进行了尝试。 REREC 次之间的比率几乎相同。
    【解决方案6】:

    一个python字符串一个字符列表。您现在可以对其进行迭代!

    justdigits = ""
    for char in string:
        if char.isdigit():
            justdigits += str(char)
    

    【讨论】:

    • 这将创建一堆字符串('1''12' 等),这是完全没有必要的。
    • @DJV:实际上,CPython 对此进行了优化。如果只存在一个对字符串对象的引用,就像这里的情况一样,+= 会原地增长字符串。
    • @kindall 虽然它仍然比其他任何东西都慢。
    • FWIW,我根本没有优化这个,只是简单地把它分解,向 OP 说明迭代字符串是多么容易。我认为@mgilson 的方法可能是要走的路。
    【解决方案7】:

    您可以迭代第一个字符串并通过将找到的每个数字字符添加到该新字符串来创建第二个字符串,而不是转换为列表。

    【讨论】:

      【解决方案8】:

      你试过list(x)吗??

       y = '+123-456-7890'
       c =list(y)
       c
      

      ['+', '1', '2', '3', '-', '4', '5', '6', '-', '7', '8', '9 ', '0']

      【讨论】:

      • 请在回复前阅读其他答案。你在重复一个。
      【解决方案9】:

      可以使用str.translate,你只需要给它正确的参数:

      >>> dels=''.join(chr(x) for x in range(256) if not chr(x).isdigit())
      >>> '+1-617-555-1212'.translate(None, dels)
      '16175551212'
      

      注意:这不适用于 Python2 中的 unicode 字符串,或者根本不适用于 Python3。对于这些环境,您可以创建一个自定义类以传递给unicode.translate

      >>> class C:
      ...    def __getitem__(self, i):
      ...       if unichr(i).isdigit():
      ...          return i
      ... 
      >>> u'+1-617.555/1212'.translate(C())
      u'16175551212'
      

      这也适用于非 ASCII 数字:

      >>> print u'+\u00b9-\uff1617.555/1212'.translate(C()).encode('utf-8')
      ¹6175551212
      

      【讨论】:

        猜你喜欢
        • 2010-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多