在Python中字符更改时拆分

时间:2014-04-23 21:09:39

标签: python string parsing

所以我有这个字符串。

6#666#665533999

我希望将其解析为多个小字符串(或直到字符更改)并忽略#,以便我可以像电话拨号盘一样替换6 = M or 666 = O or 9 = W

6#666#665533999 -> 6, 666, 66, 55, 33, 999

所以我使用split('#')方法移除#并且无法弄清楚下一步该做什么。我尝试过一些蛮力方法,它在一定程度上解决了它但是更容易或更优雅的解决方案?

3 个答案:

答案 0 :(得分:6)

使用itertools.groupby

>>> c = "6#666#665533999"
>>> ["".join(g) for k, g in groupby(c) if k != '#']
['6', '666', '66', '55', '33', '999']

然后有一个字典,将每个集合映射到拨号盘中的字符。

cmap = {'77': 'Q', '9999': 'Z'} # And so forth..

答案 1 :(得分:4)

这基本上是相同的逻辑,只是整齐地包裹起来:

from itertools import groupby

phone_chars = {
    "2": " ABC",
    "3": " DEF",
    "4": " GHI",
    "5": " JKL",
    "6": " MNO",
    "7": " PQRS",
    "8": " TUV",
    "9": " WXYZ",
    "#": ["", ""]
}

def decode(digit_str):
    return "".join(phone_chars[ch][len(list(it))] for ch,it in groupby(digit_str))

然后

>>> print(decode("6#666#665533999"))
MONKEY

修改

Python非常好online documentation

itertools.groupby接受一个输入序列和一个可选的key参数,它是一个评估函数 - 它接受一个值,对它做一些事情,然后返回结果。如果未给出key函数,则默认为identity(即key = lambda x: x,取值并返回相同的值)。

然后将此评估函数应用于输入序列中的每个项目,并返回(evaluated_value, iter(consecutive_items_having_the_same_evaluated_value))的序列。

所以

groupby("AABBBCCCDD")

让你

iter((
    ("A", iter(("A", "A"))),
    ("B", iter(("B", "B", "B"))),
    ("C", iter(("C", "C", "C"))),
    ("D", iter(("D", "D")))
))

或(演示自定义评估功能)

groupby([1, 2, 3, 4, 5, 6, 7], key=lambda x: x//3)

给出

iter((
    (0, iter([1, 2])),      # 1//3 == 2//3 == 0
    (1, iter([3, 4, 5])),   # 3//3 == 4//3 == 5//3 == 1
    (2, iter([6, 7]))       # 6//3 == 7//3 == 2
))

请注意,迭代器一次只能为您提供一个值,而len将无法在一个值上运行,因为无法知道迭代器可能返回多少个值。如果需要计算返回的值,最简单的方法是len(list(iterable)) - 将所有返回的值放入列表中,然后查看列表中有多少项。所以,如果我们这样做

[(ch, len(list(it))) for ch,it in groupby("6#666#665533999")]

我们得到的是

[
    ('6', 1),   # => 'M'
    ('#', 1),   # => ''
    ('6', 3),   # => 'O'
    ('#', 1),   # => ''
    ('6', 2),   # => 'N'
    ('5', 2),   # => 'K'
    ('3', 2),   # => 'E'
    ('9', 3)    # => 'Y'
]

(按设计)恰好是phone_chars中所需的索引值。我们使用索引值来获取相应的字符 - 即phone_chars['6'][1] == 'M' - 使用"".join()将它们连接在一起,然后返回结果字符串("MONKEY")。

答案 2 :(得分:3)

def encode(nums):
    return ["".join(g) for k, g in itertools.groupby(nums) if k != '#']


chars = {str(n):dict(enumerate(chrs,1)) for n,chrs in enumerate("ABC DEF GHI JKL MNO PQRS TUV WXYZ".split(), 2)}

nums = "6#666#665533999"
nums = encode(nums)
message = ''.join(chars[n[0]][len(n)] for n in nums)

In [28]: message
Out[28]: 'MONKEY'