提问人:MicroElf 提问时间:10/21/2023 最后编辑:MicroElf 更新时间:10/21/2023 访问量:91
如何将元素放入几个桶中(可能使用 itertools.combinations())?
How to put elements into few buckets (probably with itertools.combinations())?
问:
我需要遍历所有可能的组合,将初始可迭代的元素放入多个桶中。
插图:放入两个长度和ABCDEFG
3
2
-->
[ABC, DE], [ABC, DF], [ABC, DG], [ABD, CE], [ABD, EF], ..., [CDE, FG]
没有重复,每个桶中只有唯一的组合(没有排列)。
编辑:存储桶很重要,因为并被视为不同的组合(总体上仍然是相同的 5 个元素,但在存储桶中的分布不同)。而和被认为是相同的组合。
存储桶中的顺序更改不是不同的组合。在铲斗之间移动元素是不同的组合。ABC, DE
ABD, CE
ABC, DE
ACB, DE
我想我应该以某种方式使用 itertools.combinations():
itertools.combinations('ABCDEFG', 3) --> ABC, ABD, ..., EFG
或将其与某些东西结合起来。
但我正在努力弄清楚如何进一步将输出分布在多个不同长度的存储桶上。
答:
2赞
Brian61354270
10/21/2023
#1
以下是依赖于“样本空间”元素可散列的可能实现。这假设元素属于哪个桶很重要,如此特殊,并被视为两种不同的结果。[ABC, DE]
[ABD, CE]
import itertools
from typing import Iterable, Iterator, TypeVar
_T = TypeVar("_T")
def two_bin_combs(
iterable: Iterable[_T], b1: int, b2: int
) -> Iterator[tuple[tuple[_T, ...], tuple[_T, ...]]]:
space = set(iterable)
for left in itertools.combinations(space, b1):
for right in itertools.combinations(space - set(left), b2):
yield left, right
然后
sample_space = "ABCDEFG"
buckets = list(two_bin_combs(sample_space, 3, 2))
print(len(buckets))
print(buckets)
输出
210
[
(('A', 'B', 'C'), ('E', 'D')),
(('A', 'B', 'D'), ('C', 'E')),
(('A', 'B', 'E'), ('C', 'D')),
(('A', 'C', 'D'), ('E', 'B')),
(('A', 'C', 'E'), ('D', 'B'))
# ...
(('C', 'F', 'G'), ('D', 'E')),
(('D', 'E', 'F'), ('G', 'C')),
(('D', 'E', 'G'), ('F', 'C')),
(('D', 'F', 'G'), ('C', 'E')),
(('E', 'F', 'G'), ('D', 'C')),
]
请注意,输出顺序不是确定性的,因为它取决于设置的迭代顺序,该顺序可能因运行而异。
这种方法也可以推广到任意数量的 bing:
def bin_combs(
iterable: Iterable[_T], *bin_sizes: int
) -> Iterator[tuple[tuple[_T, ...], ...]]:
total_space = frozenset(iterable)
if len(total_space) < sum(bin_sizes):
raise ValueError("total size of bins exceeds size of sample space")
def _bin_combs(
space: frozenset[_T], *bin_sizes: int
) -> Iterator[tuple[tuple[_T, ...], ...]]:
if not bin_sizes:
yield ()
return
curr_size, *remaining = bin_sizes
for head in itertools.combinations(space, curr_size):
for tail in _bin_combs(space - frozenset(head), *remaining):
yield (head,) + tail
return _bin_combs(total_space, *bin_sizes)
评论
0赞
Kelly Bundy
10/21/2023
你有充分的理由而不是吗?yield from
return
0赞
Brian61354270
10/21/2023
@KellyBundy 不,我更喜欢。编辑return
1赞
Kelly Bundy
10/21/2023
有时是需要的,但几乎我总是看到它,它只是添加了一个不必要的生成器迭代器包装器,减慢了速度。
1赞
Kelly Bundy
10/21/2023
哦,我的意思是,有时在“类似”的情况下,一个函数创建了一些迭代器,然后只执行该迭代器。在这种情况下,通常更好,这就是我的意思。(例外情况是迭代器会关闭,就像不起作用一样,并且 a 保持活动状态。yield from
return
with open(filename) as f: return f
yield from
上一个:itertools 组合在嵌套的 np.array 中解析
下一个:遍历不同的列表
评论
[ABC, DE]
[ABE, DC]