【问题标题】:What's the pythonic way to split a string using a list of sizes?使用大小列表拆分字符串的pythonic方法是什么?
【发布时间】:2017-06-26 11:29:46
【问题描述】:

实现这个的pythonic方法是什么:

s = "thisismystring"
keys = [4, 2, 2, 6]
new = []
i = 0
for k in keys:
    new.append(s[i:i+k])
    i = i+k

这确实给了我['this', 'is', 'my', 'string'] 我需要的信息,但我觉得有一种更优雅的方法可以做到这一点。有什么建议吗?

【问题讨论】:

    标签: python string split substring


    【解决方案1】:

    只是因为我相信必须有办法在没有显式循环的情况下做到这一点:

    import re
    
    s = "thisismystring"
    
    keys = [4, 2, 2, 6]
    
    new = re.findall((r"(.{{{}}})" * len(keys)).format(*keys), s)[0]
    
    print(new)
    

    输出

    ('this', 'is', 'my', 'string')
    

    【讨论】:

      【解决方案2】:

      可以使用islice。可能效率不高,但至少可能有趣且简单。

      >>> from itertools import islice
      >>> s = 'thisismystring'
      >>> keys = [4, 2, 2, 6]
      
      >>> it = iter(s)
      >>> [''.join(islice(it, k)) for k in keys]
      ['this', 'is', 'my', 'string']
      

      【讨论】:

      • 我已经考虑过了,但是使用字符串所需的''.join() 就不那么优雅了。它非常适合子列表,而不是子字符串!
      • @MartijnPieters 是的,我也不是很兴奋。尽管对于列表,它看起来是一样的,除了 list 而不是 ''.join。差别不大。
      • 好点; tuple() 用于子元组,list() 用于子列表,''.join() 用于子字符串。
      【解决方案3】:

      你可以使用itertools.accumulate(),也许:

      from itertools import accumulate
      
      s = "thisismystring"
      keys = [4, 2, 2, 6]
      new = []
      start = 0
      for end in accumulate(keys):
          new.append(s[start:end])
          start = end
      

      您可以通过添加另一个从零开始的 accumulate() 调用来内联 start 值:

      for start, end in zip(accumulate([0] + keys), accumulate(keys)):
          new.append(s[start:end])
      

      这个版本可以做成列表推导式:

      [s[a:b] for a, b in zip(accumulate([0] + keys), accumulate(keys))]
      

      后一版本的演示:

      >>> from itertools import accumulate
      >>> s = "thisismystring"
      >>> keys = [4, 2, 2, 6]
      >>> [s[a:b] for a, b in zip(accumulate([0] + keys), accumulate(keys))]
      ['this', 'is', 'my', 'string']
      

      双重累加可以替换为tee(),包裹在pairwise() function from the itertools documentation中:

      from itertools import accumulate, chain, tee
      
      def pairwise(iterable):
          "s -> (s0,s1), (s1,s2), (s2, s3), ..."
          a, b = tee(iterable)
          next(b, None)
          return zip(a, b)
      
      [s[a:b] for a, b in pairwise(accumulate(chain([0], keys)))]
      

      我添加了一个itertools.chain() call 来作为起始位置 0 的前缀,而不是使用串联创建一个新的列表对象。

      【讨论】:

        【解决方案4】:

        我会使用 enumerate 来累积:

        [s[sum(keys[:i]): sum(keys[:i]) + k] for i, k in enumerate(keys)]
        

        用你的例子:

        >>> s = "thisismystring"
        >>> keys = [4, 2, 2, 6]
        >>> new = [s[sum(keys[:i]): sum(keys[:i]) + k] for i, k in enumerate(keys)]
        >>> new
        ['this', 'is', 'my', 'string']
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-13
          • 2021-10-16
          • 2012-08-02
          • 1970-01-01
          • 1970-01-01
          • 2012-05-24
          相关资源
          最近更新 更多