簡體   English   中英

Python近似分組

[英]Python approximate group-by

我想按其值對字典鍵進行分組。 但是,這些值僅近似相等。 在這種情況下進行分組的最好方法是什么。 我有:

buckets = defaultdict(list)
for k, v in my_dict.iteritems():
    closest = next((rep for rep in buckets if abs(rep - v) < 1e-3), None)
    if closest:
        buckets[closest].append(k)
    else:
        buckets[v].append(k)

任何itertools魔術或其他可以簡化此操作/使其更具有pythonic的功能,或者這是我能做的最好的事情嗎?

您的算法為O(n**2)因為它在O(n)循環內執行O(n)運算:

for k, v in my_dict.iteritems():
    closest = next((rep for rep in buckets if abs(rep - v) < 1e-3), None)

通過按值對my_dict.items()進行排序,然后循環遍歷已排序的項,可以將其設置為O(n log n) 請注意,如果bucketsOrderedDict ,則無需for rep in bucketsfor rep in buckets ,只需查看最后一個存儲桶,因為OrderedDict的鍵將按排序順序。 因此,如果下一個值接近任何存儲桶,則它必須接近最后一個存儲桶。 因此,通過使用OrderedDict ,您不需要遍歷所有存儲桶。 只需與最后一個比較即可:

import random
random.seed(123)
N = 10
my_dict = dict(zip(range(N), [random.randint(0, 10)/10.0 for k in range(N)]))
print(my_dict)    
# {0: 0.0, 1: 0.0, 2: 0.4, 3: 0.1, 4: 0.9, 5: 0.0, 6: 0.5, 7: 0.3, 8: 0.9, 9: 0.1}

import operator
import collections
items = sorted(my_dict.items(), key=operator.itemgetter(1))
buckets = collections.OrderedDict([(items[0][1], [items[0][0]])])
for k, v in items[1:]:
    last_val = next(reversed(buckets))
    closest = last_val if abs(last_val - v) < 1e-3 else v
    buckets.setdefault(closest, []).append(k) 

print(buckets)

版畫

OrderedDict([(0.0, [0, 1, 5]), (0.1, [3, 9]), (0.3, [7]), (0.4, [2]), (0.5, [6]), (0.9, [4, 8])])

這會稍微有點“ pythonic”:

buckets = defaultdict(list)
for k, v in my_dict.iteritems():
    try:
        closest = next((rep for rep in buckets if abs(rep - v) < 1e-3))
        buckets[closest].append(k)
    except StopIteration:
        buckets[v].append(k)

除了您的代碼效率低下外,由於.itetitems()順序可能是任意的,因此也不保證每次都相同或任何特定的結果。 要解決這兩個問題,您只需使用鍵功能:

key = lambda x: round(x, 3)

然后,您按照通常的方式進行分組,但是使用key(v)作為索引:

buckets = defaultdict(list)
for k, v in my_dict.iteritems():
    buckets[key(v)].append(k)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM