2012-10-04 25 views
11

我經常想要在python中挖掘無序集合。 itertools.groubpy做的是正確的事情,但幾乎總是需要按摩來先排序項目並在消耗之前捕獲迭代器。將項目分組爲桶的簡單方法

是否有任何快速的方法來獲得這種行爲,無論是通過標準的Python模塊或簡單的Python成語?

>>> bucket('thequickbrownfoxjumpsoverthelazydog', lambda x: x in 'aeiou') 
{False: ['t', 'h', 'q', 'c', 'k', 'b', 'r', 'w', 'n', 'f', 'x', 'j', 'm', 'p', 
    's', 'v', 'r', 't', 'h', 'l', 'z', 'y', 'd', 'g'], 
True: ['e', 'u', 'i', 'o', 'o', 'u', 'o', 'e', 'e', 'a', 'o']} 
>>> bucket(xrange(21), lambda x: x % 10) 
{0: [0, 10, 20], 
1: [1, 11], 
2: [2, 12], 
3: [3, 13], 
4: [4, 14], 
5: [5, 15], 
6: [6, 16], 
7: [7, 17], 
8: [8, 18], 
9: [9, 19]} 
+1

我一定是偏向惡補一切納入討論一行通過詢問「單線」。我只是將它改爲「python成語」,但當然,如果它真的很短,我不會抱怨。 –

回答

17

這又拿出了前幾次 - (1)(2)(3) - 並有一個在itertools recipes分區配方,但據我所知,沒有什麼標準庫。雖然我很驚訝几几周前accumulate,那麼誰知道這些日子裏潛伏着什麼呢? :^)

當我需要這種行爲,我用

from collections import defaultdict 

def partition(seq, key): 
    d = defaultdict(list) 
    for x in seq: 
     d[key(x)].append(x) 
    return d 

,並與我天獲得。

+0

+1漂亮,簡單,清晰的解決方案 – wim

+1

對於defaultdict的使用+1,我總是忘記它存在,並將其包裝在一個很好的函數中。 – grieve

4

下面是一個簡單的兩個班輪

d = {} 
for x in "thequickbrownfoxjumpsoverthelazydog": d.setdefault(x in 'aeiou', []).append(x) 

編輯:

只是增加你的其他情況下的完整性。

d={} 
for x in xrange(21): d.setdefault(x%10, []).append(x) 
+0

我總是發現'defaultdict'比d.setdefault.etc類型的技巧更好 – wim

+0

@wim:是的,我總是忘記它存在。這就是爲什麼我投票選舉帝斯曼的答案。 – grieve

+2

wim:其實我喜歡'setdefault'比'defaultdict'更好。這兩種代碼的數量幾乎相同,但是'setdefault'是明確的,你可以在現有的字典中使用它,就像你發現你需要它一樣。 –

-1

編輯:

使用DSM的回答作爲開始,這裏是一個稍微更簡潔,一般的答案:

d = defaultdict(list) 
map(lambda x: d[x in 'aeiou'].append(x),'thequickbrownfoxjumpsoverthelazydog') 

d = defaultdict(list) 
map(lambda x: d[x %10].append(x),xrange(21)) 

這裏是一個兩個班輪:

d = {False:[],True:[]} 
filter(lambda x: d[True].append(x) if x in 'aeiou' else d[False].append(x),"thequickbrownfoxjumpedoverthelazydogs") 

哪當然可以製成一個班輪:

d = {False:[],True:[]};filter(lambda x: d[True].append(x) if x in 'aeiou' else d[False].append(x),"thequickbrownfoxjumpedoverthelazydogs") 
+0

-1這些鍵並不總是False和True,它們應該是可調用的輸出 – wim

+0

我推薦''在'thequickbrownfoxjumpsoverthelazydog'中使用x:'x'在'aeiou']。append(x)'form (如在悲傷的答案中)。我不是使用'map'做副作用並丟掉價值的粉絲。 –

+0

悲傷答案的問題雖然效果很好,但它的計算成本更高一些。 (它調用每個元素的setdefault,重複或不)。我喜歡DSM的答案,但我想看看是否可以得到一個班輪(或接近它)。 – korylprince

2

下面是partition()從當謂詞是布爾上方的變體中,避免dict/defaultdict的成本:

def boolpartition(seq, pred): 
    passing, failing = [], [] 
    for item in seq: 
     (passing if pred(item) else failing).append(item) 
    return passing, failing 

用法示例:

>>> even, odd = boolpartition([1, 2, 3, 4, 5], lambda x: x % 2 == 0) 
>>> even 
[2, 4] 
>>> odd 
[1, 3, 5] 
0

如果它的一個pandas.DataFrame以下也適用,utilizi NG pd.cut()

from sklearn import datasets 
import pandas as pd 

# import some data to play with 
iris = datasets.load_iris() 
df_data = pd.DataFrame(iris.data[:,0]) # we'll just take the first feature 

# bucketize 
n_bins = 5 
feature_name = iris.feature_names[0].replace(" ", "_") 
my_labels = [str(feature_name) + "_" + str(num) for num in range(0,n_bins)] 
pd.cut(df_data[0], bins=n_bins, labels=my_labels) 

產生

0  0_1 
1  0_0 
2  0_0 
[...] 

如果您沒有設置labels,輸出會喜歡這個

0  (5.02, 5.74] 
1  (4.296, 5.02] 
2  (4.296, 5.02] 
[...] 
相關問題