在Python中有效枚举有序子集

时间:2015-07-07 22:55:31

标签: python iterator generator combinations itertools

我不确定我正在尝试编写的代码的相应数学术语。我想生成唯一整数的组合,其中每个组合的“有序子集”用于排除某些后来的组合。

希望一个例子可以说清楚:

from itertools import chain, combinations
​
mylist = range(4)
max_depth = 3

rev = chain.from_iterable(combinations(mylist, i) for i in xrange(max_depth, 0, -1))
for el in list(rev):
    print el

该代码导致输出包含我想要的所有子集,但也包含一些我不需要的额外子集。我已手动插入注释以指示我不想要的元素。

(0, 1, 2)
(0, 1, 3)
(0, 2, 3)
(1, 2, 3)
(0, 1)  # Exclude: (0, 1, _) occurs as part of (0, 1, 2) above
(0, 2)  # Exclude: (0, 2, _) occurs above
(0, 3)  # Keep
(1, 2)  # Exclude: (1, 2, _) occurs above
(1, 3)  # Keep: (_, 1, 3) occurs above, but (1, 3, _) does not
(2, 3)  # Keep
(0,)    # Exclude: (0, _, _) occurs above
(1,)    # Exclude: (1, _, _) occurs above
(2,)    # Exclude: (2, _) occurs above
(3,)    # Keep

因此,我的生成器或迭代器的所需输出将是:

(0, 1, 2)
(0, 1, 3)
(0, 2, 3)
(1, 2, 3)
(0, 3)
(1, 3)
(2, 3)
(3,)  

我知道我可以列出所有(想要的和不需要的)组合,然后筛选出我不想要的组合,但我想知道是否有更高效的,基于生成器或迭代器的方式。

2 个答案:

答案 0 :(得分:3)

您正尝试排除以前返回的组合的前缀的任何组合。这样做很简单。

  • 如果元组if var == var2: commands things_outside_of_IF_statement 的长度为t,则它不能是先前返回的元组的前缀,因为任何元组的前缀都必须更长
  • 如果元组max_deptht结尾,那么它就不能成为先前返回的元组的前缀,因为没有任何元素可以合法地添加到结尾mylist[-1]扩展它。
  • 如果元组t的长度小于t且未以max_depth结尾,则mylist[-1]是先前返回的元组t的前缀},并且不应返回t + (mylist[-1],)

因此,您应该生成的组合恰好是长度为t的组合,以及以max_depth结尾的较短组合。以下代码执行此操作,与原始代码完全相同,并正确处理mylist[-1]等案例:

maxdepth > len(mylist)

(我在此假设在def nonprefix_combinations(iterable, maxlen): iterable = list(iterable) if not (iterable and maxlen): return for comb in combinations(iterable, maxlen): yield comb for length in xrange(maxlen-2, -1, -1): for comb in combinations(iterable[:-1], length): yield comb + (iterable[-1],) 的情况下,您仍然不想在输出中包含空元组,即使对于maxdepth == 0,它也不是#39; ta先前返回的元组的前缀。如果在这种情况下确实需要空元组,则可以将maxdepth == 0更改为if not (iterable and maxlen)。)

答案 1 :(得分:1)

我注意到你想要的输出中有一个有趣的模式,我有一个生成它的生成器。这适用于所有情况吗?

xtable2 <- function(x, ...) {  sm <- x[['coefficients']]; ncol <- ncol(sm)
                             whch<- grep("Pr", colnames(sm))
                             digs <- rep(4, ncol+1); digs[whch+1] <- 2
                             disp <-rep("f", ncol+1); disp[whch+1] <- "g"
                  xtable(x, digits= digs, display=disp, ...) }

> tab <- as.FlexTable(xtable2(s)); tab

以下是我对逻辑的解释:

from itertools import combinations

def orderedSetCombination(iterable, r):
    # Get the last element of the iterable
    last = (iterable[-1], )
    # yield all the combinations of the iterable without the
    # last element
    for iter in combinations(iterable[:-1], r):
        yield iter
    # while r > 1 reduce r by 1 and yield all the combinations
    while r>1:
        r -= 1
        for iter in combinations(iterable[:-1], r):
            yield iter+last
    # yield the last item
    yield last

iter = [0,1,2,3]

for el in (list(orderedSetCombination(iter, 3))):
    print(el)