将字符串拆分为连续计数?

时间:2015-09-09 00:22:45

标签: python string list-comprehension

例如,如果给定的字符串是:

3 a, 4 b, 2 c, 1 d, 1 a, 4 e

我想说的是:

while source!="":
    leading = source[0]
    c=0
    while source!="" and source[0]==leading:
        c+=1
        source=source[1:]
    print(c, leading)

使用强力循环在Python中很容易做到,但我想知道是否有更多Pythonic /更清晰的单行方式。

我的蛮力:

enc_nums = [(x + y) % 27 for (x, y) in zip(nums, rk_nums)]
...
dec_nums = [(x - y) % 27 for (x, y) in zip(enc_nums, rk_nums)]

2 个答案:

答案 0 :(得分:9)

使用Counter计算字符串中每个不同字母的数量,无论位置如何:

>>> s="aaabbbbccdaeeee"
>>> from collections import Counter
>>> Counter(s)
Counter({'a': 4, 'b': 4, 'e': 4, 'c': 2, 'd': 1})

如果字符串中的位置具有含义:

,则可以使用groupby
from itertools import groupby
li=[]
for k, l in groupby(s):
    li.append((k, len(list(l))))

print li

打印:

[('a', 3), ('b', 4), ('c', 2), ('d', 1), ('a', 1), ('e', 4)]

可以减少到列表理解:

[(k,len(list(l))) for k, l in groupby(s)]

你甚至可以使用正则表达式:

>>> [(m.group(0)[0], len(m.group(0))) for m in re.finditer(r'((\w)\2*)', s)] 
[('a', 3), ('b', 4), ('c', 2), ('d', 1), ('a', 1), ('e', 4)]

答案 1 :(得分:0)

有多种解决问题的方法。 @dawg已经发布了最好的解决方案,但是如果由于某些原因您不被允许使用Counter()(也许是工作面试或学校任务),那么您实际上可以通过几种方式解决问题。

from collections import Counter, defaultdict

def counter_counts(s):
    """ Preferred method using Counter()


    Arguments:
        s {string} -- [string to have each character counted]

    Returns:
        [dict] -- [dictionary of counts of each char]
    """

    return Counter(s)

def default_counts(s):
    """ Alternative solution using defaultdict


    Arguments:
        s {string} -- [string to have each character counted]

    Returns:
        [dict] -- [dictionary of counts of each char]
    """

    counts = defaultdict(int)  # each key is initalized to 0
    for char in s:
        counts[char] += 1  # increment the count of each character by 1

    return counts

def vanilla_counts_1(s):
    """ Alternative solution using a vanilla dicitonary


    Arguments:
        s {string} -- [string to have each character counted]

    Returns:
        [dict] -- [dictionary of counts of each char]
    """

    counts = {}
    for char in s:
        # we have to manually check that each value is in the dictionary before attempting to increment it
        if char in counts:
            counts[char] += 1
        else:
            counts[char] = 1

    return counts

def vanilla_counts_2(s):
    """ Alternative solution using a vanilla dicitonary
    This version uses the .get() method to increment instead of checking if a key already exists


    Arguments:
        s {string} -- [string to have each character counted]

    Returns:
        [dict] -- [dictionary of counts of each char]
    """

    counts = {}
    for char in s:
         # the second argument in .get() is the default value if we dont find the key
        counts[char] = counts.get(char, 0) + 1 

    return counts

为了好玩,让我们看看每种方法的执行情况。

对于s = "aaabbbbccdaeeee"和10,000次运行:

Counter: 0.0330204963684082s
defaultdict: 0.01565241813659668s
vanilla 1: 0.01562952995300293s
vanilla 2: 0.015581130981445312s

(实际上令人惊讶的结果)

现在让我们测试一下,如果将字符串设置为《创世纪》的整个纯文本版本并运行1000次,会发生什么情况:

Counter: 8.500739336013794s
defaultdict: 14.721554040908813s
vanilla 1: 18.089043855667114s
vanilla 2: 27.01840090751648s

看起来创建Counter()对象的开销变得不那么重要了!

(这些不是很科学的测试,但是有点有趣)。