在python中组合

时间:2012-12-04 17:10:44

标签: python algorithm sorting combinations combinatorics

我有四个值

age = 23
gender = "M"
city ="Delhi"
religion = "Muslim"

我需要通过每个组合排列这些空值,例如 -

23 * * *
23 M * *
23 M Delhi *
23 M Delhi Muslim
* M * *
* M Delhi *
* M Delhi Muslim
* * Delhi *
* * Delhi Muslim
* * * Muslim
* * * *

我需要在列表中按升序排列维数。因此,具有一个值的组合应该位于顶部。我有30多个属性,所以我需要一种在Python中自动执行此操作的方法

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

以下内容如何:

In [21]: attrib = (23, "M", "Delhi", "Muslim")

In [25]: comb = list(itertools.product(*((a, None) for a in attrib)))

In [26]: comb
Out[26]: 
[(23, 'M', 'Delhi', 'Muslim'),
 (23, 'M', 'Delhi', None),
 (23, 'M', None, 'Muslim'),
 (23, 'M', None, None),
 (23, None, 'Delhi', 'Muslim'),
 (23, None, 'Delhi', None),
 (23, None, None, 'Muslim'),
 (23, None, None, None),
 (None, 'M', 'Delhi', 'Muslim'),
 (None, 'M', 'Delhi', None),
 (None, 'M', None, 'Muslim'),
 (None, 'M', None, None),
 (None, None, 'Delhi', 'Muslim'),
 (None, None, 'Delhi', None),
 (None, None, None, 'Muslim'),
 (None, None, None, None)]

现在,如果我正确理解您的排序要求,则应执行以下操作:

In [27]: sorted(comb, key=lambda x:sum(v is not None for v in x))
Out[27]: 
[(None, None, None, None),
 (23, None, None, None),
 (None, 'M', None, None),
 (None, None, 'Delhi', None),
 (None, None, None, 'Muslim'),
 (23, 'M', None, None),
 (23, None, 'Delhi', None),
 (23, None, None, 'Muslim'),
 (None, 'M', 'Delhi', None),
 (None, 'M', None, 'Muslim'),
 (None, None, 'Delhi', 'Muslim'),
 (23, 'M', 'Delhi', None),
 (23, 'M', None, 'Muslim'),
 (23, None, 'Delhi', 'Muslim'),
 (None, 'M', 'Delhi', 'Muslim'),
 (23, 'M', 'Delhi', 'Muslim')]

我使用过None *,但使用后者却很简单。

当然,有30个属性,你正在寻找〜10亿个组合,所以列表的扁平化以及随后的排序可能不起作用。但是,无论如何,你能用10亿个条目做些什么呢?

答案 1 :(得分:4)

NPE's answer通过在内存中构建完整的子集列表然后对其进行排序来解决问题。这需要O(2 n )空间和O( n 2 2 n < / em> )时间。如果这是不可接受的,那么这是一种在O( n )空间中生成子集的方法和O( n 2 n < / sup>)时间。

from itertools import combinations

def subsets(s, placeholder = None):
    """
    Generate the subsets of `s` in order of size.
    Use `placeholder` for missing elements (default: None).
    """
    s = list(s)
    n = len(s)
    r = range(n)
    for i in range(n + 1):
        for c in combinations(r, i):
            result = [placeholder] * n
            for j in c:
                result[j] = s[j]
            yield result

>>> from pprint import pprint
>>> pprint(list(subsets([23, 'M', 'Delhi', 'Muslim'])))
[[None, None, None, None],
 [23, None, None, None],
 [None, 'M', None, None],
 [None, None, 'Delhi', None],
 [None, None, None, 'Muslim'],
 [23, 'M', None, None],
 [23, None, 'Delhi', None],
 [23, None, None, 'Muslim'],
 [None, 'M', 'Delhi', None],
 [None, 'M', None, 'Muslim'],
 [None, None, 'Delhi', 'Muslim'],
 [23, 'M', 'Delhi', None],
 [23, 'M', None, 'Muslim'],
 [23, None, 'Delhi', 'Muslim'],
 [None, 'M', 'Delhi', 'Muslim'],
 [23, 'M', 'Delhi', 'Muslim']]

答案 2 :(得分:1)

查看itertools,它有combinations

的方法