所以我有这个字符串。
6#666#665533999
我希望将其解析为多个小字符串(或直到字符更改)并忽略#
,以便我可以像电话拨号盘一样替换6 = M or 666 = O or 9 = W
。
6#666#665533999 -> 6, 666, 66, 55, 33, 999
所以我使用split('#')
方法移除#
并且无法弄清楚下一步该做什么。我尝试过一些蛮力方法,它在一定程度上解决了它但是更容易或更优雅的解决方案?
答案 0 :(得分:6)
>>> 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'