<p>您已导入<code>itertools</code>,但未使用它。这里有一个<a href="https://docs.python.org/3/library/itertools.html#itertools.combinations_with_replacement" rel="nofollow noreferrer">^{<cd2>}</a>的解决方案</p>
<p>选取长度递增的组合,从1到<code>max_elems</code>,设置为<code>upper_limit</code>除以值中的最小数。(假设0和负数不作为值出现。)</p>
<pre class="lang-py prettyprint-override"><code>def subsets(lst, upper_limit , lower_limit):
max_elems = upper_limit // min(n[1] for n in lst)
for num_elems in range(1, max_elems+1):
for combination in itertools.combinations_with_replacement(lst, r=num_elems):
total = sum(j[1] for j in combination) # values, index 1
if lower_limit <= total <= upper_limit:
yield [j[0] for j in combination] # letters, index 0
list(subsets(items, 29, 20))
</code></pre>
<p>输出:</p>
<pre><code>[['c'],
['a', 'b'],
['a', 'c'],
['a', 'd'],
['b', 'b'],
['b', 'd'],
['d', 'd'],
['a', 'a', 'a'],
['a', 'a', 'b'],
['a', 'a', 'd'],
['a', 'a', 'a', 'a']]
</code></pre>
<p>(顺便说一句,ppl通常会执行<code>(lower_limit, upper_limit)</code>,而不是相反;但是我让您的函数调用保持原样。)</p>
<p>内循环中的另一个优化:</p>
<pre><code>for combination in itertools.combinations_with_replacement(lst, r=num_elems):
letters, numbers = zip(*combination)
if lower_limit <= sum(numbers) <= upper_limit:
yield letters # or list(letters) if you don't want a tuple
</code></pre>
<hr/>
<p>要修改<em>现有代码</em>以包含字母,而不是执行<code>j[1] for j in items</code>,请直接使用<code>j</code>,以便它传入字母和值。只有在检查总和时,才使用<code>[1]</code>中的值。在<code>subsets()</code>函数中执行此操作非常重要,因为如果只使用结果执行此操作,则需要再次检查组合<em>,</em>,因为(7,7,7)可以是('a','a','a')或('e','e'),也可以是'a','e'和'z'的所有组合,因为它们都是7。然后你需要过滤掉重复的</p>