2012-10-16 72 views
0

我有一個像通過鍵生成一個列表的所有可能的子列表

[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的關鍵字。

如何使用這些密鑰將我的大列表分成更小的子列表?甚至有一種方法可以在不使用密鑰的情況下執行此操作。無論哪種方式,我不知道該怎麼做,看着其他堆棧溢出問題有eben在球場,但不完全是這個問題。

回答

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]應該是一個列表。

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):不過,如果我使用的是傳統的dict,我試圖append到一個不存在的鍵值,我會如下得到一個KeyError。如果我定義了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,我想創建這樣一個字典,一個值從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完成!希望有幫助

+0

你知不知道你是一個TOTAL BOSS!?!?!?因爲你。 – nebffa

+0

ps。如果你很樂意爲zip之類的東西提供一些解釋,defaultdict會做得很棒 - 有時候這些文檔有點複雜,像這樣的例子使它更簡單。這是一個獎勵,儘管 – nebffa

+1

@nebffa defaultdict是允許字典具有默認值的字典的擴展。我們需要其中之一的原因是因爲'append'功能;我們將值添加到列表中。問題是,如果這個列表在'append'時不存在,我們會得到一個錯誤。 Defaultdict可以防止這種情況。 zip是一個函數,它從一個列表中獲取第一個對象,並從一個列表中獲取第二個對象,將它們放入一個元組中,然後將其輸出到列表中。並重申,在列表期間。我們在這裏使用它來爲你的價值分配你的鑰匙,準備字典。 – kreativitea

相關問題