<p><a href="https://github.com/erikrose/more-itertools" rel="nofollow noreferrer">^{<cd1>} third-party library</a>有一个解决<a href="https://en.wikipedia.org/wiki/Run-length_encoding" rel="nofollow noreferrer">run length encoding/compression</a>问题的工具。参见<a href="https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.run_length" rel="nofollow noreferrer">the docs</a>中的示例:</p>
<pre><code> >>> compressed = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> list(run_length.decode(compressed))
['a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd']
</code></pre>
<p>这个工具使用起来很简单。理想情况下,您应该传入一个元组列表的输入,每个元组包含一个字符串和一个乘法整数。你知道吗</p>
<p><strong>代码</strong></p>
<p>在这里,我们将实现一个<code>parse</code>helper函数,将您的输入转换为适当的格式。你知道吗</p>
<pre><code>import itertools as it
import more_itertools as mit
def parse(iterable):
"""Return a list of string, multiplier pairs."""
iterable = iterable.replace("(", "").replace(")", "")
pred = lambda x: x.isalpha()
non_numbers = ("".join(g) for k, g in it.groupby(iterable, pred) if k)
numbers = (int(list(g)[0]) for k, g in it.groupby(iterable, pred) if not k)
zipped = list(it.zip_longest(non_numbers, numbers, fillvalue=1))
return zipped
</code></pre>
<p>演示</p>
<pre><code>>>> iterable = "(BA)4B5A"
>>> # Application
>>> "".join(mit.run_length.decode(parse(iterable)))
'BABABABABBBBBA'
>>> # Tests
>>> assert parse(iterable) == [("BA", 4), ("B", 5), ("A", 1)]
>>> assert list(mit.run_length.decode(parse(iterable))) == ["BA", "BA", "BA", "BA", "B", "B", "B", "B", "B", "A"]
</code></pre>
<hr/>
<p><strong>细节</strong></p>
<p><code>parse</code>函数从输入iterable中删除括号。然后用<code>itertools.groupby</code>构建两个生成器:一个用于字符串组,另一个用于乘法器组。这些组被压缩在一起。<code>itertools.zip_longest</code>接受<code>fillvalue</code>参数,因此如果输入iterable以字符串结尾(如在示例输入中),则默认乘数为<code>1</code>。你知道吗</p>
<p><code>run_length.decode</code>方法在这里实现:</p>
<pre><code>class run_length(object):
...
def decode(iterable):
return list(it.chain.from_iterable(it.repeat(k, n) for k, n in iterable))
</code></pre>
<p>注意:在命令行提示符中使用<code>> pip install more_itertools</code>来安装这个库。你知道吗</p>
<p>其他参考资料</p>
<ul>
<li>关于<code>itertools.groupby</code>工作原理的<a href="https://stackoverflow.com/a/45873519/4531270">post</a></li>
<li>有关详细信息,请参见<a href="https://github.com/erikrose/more-itertools/blob/master/more_itertools/more.py#L1891" rel="nofollow noreferrer">source code</a>和<a href="https://github.com/erikrose/more-itertools/pull/172" rel="nofollow noreferrer">GitHub issue</a></li>
</ul>