按键生成列表的所有可能子列表

时间:2012-10-16 23:52:46

标签: python

我有像

这样的数据
[2, 2, 2, 2, 2, 3, 13, 113]

然后我想通过自己生成的密钥对单独的列表进行排序。实际上我想生成所有可能的列表。

一些例子:

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [0, 0, 1, 2, 1, 3,  3,   1]
sublists: [2, 2], [2, 2, 113], [2], [3, 13]

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [0, 1, 0, 0, 0, 1,  1,   0]
sublists: [2, 2, 2, 2, 113], [2, 3, 13]

values: [2, 2, 2, 2, 2, 3, 13, 113]
keys:   [2, 3, 0, 0, 4, 4,  1,   3]
sublists: [2, 2], [13], [2], [2, 113], [2, 3]

所有可能的密钥都由

生成
def generate_keys(prime_factors):
    key_size = len(prime_factors) - 1
    key_values = [str(i) for i in range(key_size)]

    return list(itertools.combinations_with_replacement(key_values, \
        len(prime_factors)))

然后我想我可以使用键将值转移到子列表中。那是我坚持的部分。我认为itertools.groupby将是我的解决方案,但经过进一步调查,我发现无法使用我的自定义列表作为groupby的键。

如何使用这些键将我的大列表拆分为较小的子列表?甚至可以在不使用键的情况下执行此操作。无论哪种方式,我都不知道如何做到这一点,并且看看其他Stack Overflow问题已经在球场上发挥作用,但不完全是这个问题。

1 个答案:

答案 0 :(得分:3)

这样做你想要的:

def sift(keys, values):
    answer = collections.defaultdict(list)
    kvs = zip(keys, values)
    for k,v in kvs:
        answer[k].append(v)
    return [answer[k] for k in sorted(answer)]

In [205]: keys = [0, 0, 1, 2, 1, 3,  3,   1]

In [206]: values = [2, 2, 2, 2, 2, 3, 13, 113]

In [207]: sift(keys,values)
Out[207]: [[2, 2], [2, 2, 113], [2], [3, 13]]

<强>解释

collections.defaultdict是一个方便的dict类,它允许您定义在您尝试操作的字典中不存在键时应该发生的事情。例如,在我的代码中,我有answer[k].append(v)。我们知道appendlist函数,因此我们知道answer[k]应该是一个列表。但是,如果我使用的是传统的dict并尝试append来表示不存在的密钥的价值,我会得到KeyError,如下所示:

In [212]: d = {}

In [213]: d[1] = []

In [214]: d
Out[214]: {1: []}

In [215]: d[1].append('one')

In [216]: d[1]
Out[216]: ['one']

In [217]: d
Out[217]: {1: ['one']}

In [218]: d[2].append('two')
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
/Users/USER/<ipython-input-218-cc58f739eefa> in <module>()
----> 1 d[2].append('two')

KeyError: 2

这是唯一可行的,因为我定义了answer = collections.defaultdict(list)。如果我定义了answer = collections.defaultdict(int),我会得到一个不同的错误 - 会告诉我int个对象没有append方法。

另一方面,

zip需要两个list s(实际上,它至少需要两个iterables),我们称之为list1list2并返回一个元组列表,其中i元组包含两个对象。第一个是list1[i],第二个是list2[i]。如果list1list2长度不等,则len(zip(list1, list2))len(list1)中的len(list2)值会较小(即min(len(list1), len(list2))

我压缩keysvalues之后,我想创建一个dict,将keys的值映射到values的值列表。这就是我使用defaultdict的原因,因此在附加到其值之前,我不必检查其中是否存在密钥。如果我使用传统的词典,我将不得不这样做:

answer = {}
kvs = zip(keys, values)
for k,v, in kvs:
    if k in answer:
        answer[k].append(v)
    else:
        answer[k] = [v]

现在您有一个dict(或类似dict的对象),它将keys中的值映射到共享相同密钥的int列表,所有您需要做的是按排序顺序获取answer的值列表,按answer的键排序。 sorted(answer)以排序顺序为我提供了所有answer个键的列表。

一旦我有了这个排序键列表,我所要做的就是获取它们的值,这些值是整数列表,并将所有这些列表放入一个大列表中并返回该大列表。

... annnnnd完成!希望有所帮助