【问题标题】:Keeping only certain characters in a string using Python?使用 Python 只保留字符串中的某些字符?
【发布时间】:2013-03-23 04:26:42
【问题描述】:

在我的程序中,我有一个这样的字符串:

ag ct oso gcota

使用 python,我的目标是去掉空格,只保留 a、t、c 和 g 字符。 我了解如何摆脱空白(我只是使用 line = line.replace(" ", ""))。但是,当它们可能是字母表中的任何其他字母时,我怎样才能摆脱我不需要的字符呢?

【问题讨论】:

    标签: python string replace


    【解决方案1】:

    我可能会这样做:

    chars_i_want = set('atcg')
    final_string = ''.join(c for c in start_string if c in chars_i_want)
    

    这可能是最简单的方法。


    另一种选择是使用str.translate 来完成这项工作:

    import string
    chars_to_remove = string.printable.translate(None,'acgt')
    final_string = start_string.translate(None,chars_to_remove)
    

    我不确定哪个会更好。需要通过timeit 定时才能确定。


    更新:时间安排!

    import re
    import string
    
    def test_re(s,regex=re.compile('[^atgc]')):
        return regex.sub(s,'')
    
    def test_join1(s,chars_keep=set('atgc')):
        return ''.join(c for c in s if c in chars_keep)
    
    def test_join2(s,chars_keep=set('atgc')):
        """ list-comp is faster, but less 'idiomatic' """
        return ''.join([c for c in s if c in chars_keep])
    
    def translate(s,chars_to_remove = string.printable.translate(None,'acgt')):
        return s.translate(None,chars_to_remove)
    
    import timeit
    
    s = 'ag ct oso gcota'
    for func in "test_re","test_join1","test_join2","translate":
        print func,timeit.timeit('{0}(s)'.format(func),'from __main__ import s,{0}'.format(func))
    

    遗憾的是(对我而言),regex 在我的机器上获胜:

    test_re 0.901512145996
    test_join1 6.00346088409
    test_join2 3.66561293602
    translate 1.0741918087
    

    【讨论】:

    • regex.sub() 的使用不正确,因此时机不对。它应该是 regex.sub('', s) 而不是相反。
    【解决方案2】:

    一个非常优雅和快速的方法是使用正则表达式:

    import re
    
    str = 'ag ct oso gcota'
    str = re.sub('[^atcg]', '', str)
    
    """str is now 'agctgcta"""
    

    【讨论】:

      【解决方案3】:

      人们在投票之前是否测试了 mgilson 的 test_re() 函数? re.sub() 的参数是相反的,所以它在一个空字符串中进行替换,并且总是返回空字符串。

      我在 python 3.4 中工作; string.translate() 只接受一个参数,一个字典。因为构建这个字典有开销,所以我把它移出了函数。公平地说,我还将正则表达式编译移出函数(这并没有产生明显的差异)。

      import re
      import string
      
      regex=re.compile('[^atgc]')
      
      chars_to_remove = string.printable.translate({ ord('a'): None, ord('c'): None, ord('g'): None, ord('t'): None })
      cmap = {}
      for c in chars_to_remove:
          cmap[ord(c)] = None
      
      def test_re(s):
          return regex.sub('',s)
      
      def test_join1(s,chars_keep=set('atgc')):
          return ''.join(c for c in s if c in chars_keep)
      
      def test_join2(s,chars_keep=set('atgc')):
          """ list-comp is faster, but less 'idiomatic' """
          return ''.join([c for c in s if c in chars_keep])
      
      def translate(s):
          return s.translate(cmap)
      
      import timeit
      
      s = 'ag ct oso gcota'
      for func in "test_re","test_join1","test_join2","translate":
          print(func,timeit.timeit('{0}(s)'.format(func),'from __main__ import s,{0}'.format(func)))
      

      以下是时间安排:

      test_re 3.3141989699797705
      test_join1 2.4452173250028864
      test_join2 2.081048655003542
      translate 1.9390292020107154
      

      太糟糕了 string.translate() 没有选项来控制如何处理不在地图中的字符。当前的实现是保留它们,但我们也可以选择删除它们,以防我们想要保留的字符远少于我们想要删除的字符(哦,你好,unicode)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-27
        • 2016-03-16
        • 1970-01-01
        • 1970-01-01
        • 2010-12-09
        • 2011-12-04
        相关资源
        最近更新 更多