2013-05-05 11 views
6

मेरा कोड वर्तमान में भारी घोंसला वाले dict में चीजों को गिनने के लिए है। मेरे पास ऐसे आइटम हैं जिन्हें 3 मानों से अनुक्रमित करने की आवश्यकता है और फिर गिना जाता है। तो, मेरे पाश से पहले, मैं प्रारंभ एक नेस्टेड defaultdict तो जैसे:भारी घोंसला वाले डिफॉल्टडिक्ट में चीजों की गिनती का अधिक पाइथोनिक तरीका

from collections import defaultdict 

type_to_count_dic = defaultdict(
     lambda: defaultdict(
      lambda: defaultdict(int) 
     ) 
    ) 

कौन सा मुझे इतना की तरह एक तंग पाश के भीतर आइटम गिनती करने के लिए अनुमति देता है:

for a in ...: 
    for b in ...: 
     for c in ...: 
      type_to_count_dic[a][b][c] += 1 

मैं उन सभी defaultdict रों आरंभ की तरह महसूस जावा जैसे कुछ में एक प्रकार की घोषणा करने की तरह बहुत कुछ लगता है। क्या ऐसा कुछ करने का कोई और मूर्खतापूर्ण/पायथनिक तरीका है?

उत्तर

8
from collections import defaultdict 

class _defaultdict(defaultdict): 
    def __add__(self, other): 
     return other 

def CountTree(): 
    return _defaultdict(CountTree) 

>>> t = CountTree() 
>>> t['a'] 
defaultdict(<function CountTree at 0x9e5c3ac>, {}) 
>>> t['a']['b']['c'] += 1 
>>> print t['a']['b']['c'] 
1 
3

आप चीजों गिनती कर रहे हैं के बाद से, आप आंतरिक सबसे dict के लिए एक काउंटर का उपयोग करना चाहिए:

import collections 
defaultdict = collections.defaultdict 
Counter = collections.Counter 

x = defaultdict(lambda: defaultdict(Counter)) 

for a in A: 
    for b in B: 
     x[a][b].update(C) 

एक काउंटर का उपयोग करते हुए आप इस तरह के most_common के रूप में उपयोगी तरीकों तक पहुँच प्रदान करेगा।

इस निर्देश के साथ आप जो करना चाहते हैं उसके आधार पर, आपको गहरी घोंसले की आवश्यकता नहीं हो सकती है। इसके बजाय, आप कुंजी के लिए एक tuple का उपयोग कर सकते हैं। उदाहरण के लिए,

import collections 
import itertools as IT 

A = range(2) 
B = 'XYZ' 
C = 'abc' 
x = collections.Counter(IT.product(A, B, C)) 
print(x) 

A = range(2) 
B = 'XYZ' 
C = 'abc' 
x = collections.Counter(IT.product(A, B, C)) 
print(x) 

पैदावार

Counter({(0, 'X', 'c'): 1, (0, 'Z', 'a'): 1, (1, 'Z', 'a'): 1, (1, 'X', 'c'): 1, (1, 'Z', 'b'): 1, (0, 'X', 'b'): 1, (0, 'Y', 'a'): 1, (1, 'Y', 'a'): 1, (0, 'Z', 'c'): 1, (1, 'Z', 'c'): 1, (0, 'X', 'a'): 1, (0, 'Y', 'b'): 1, (1, 'X', 'a'): 1, (1, 'Y', 'b'): 1, (0, 'Z', 'b'): 1, (1, 'Y', 'c'): 1, (1, 'X', 'b'): 1, (0, 'Y', 'c'): 1}) 
2

पैदावार मैं तुम्हें केवल प्रत्येक काउंटर करने के लिए जोड़ रहे हैं यह सोचते कर रहा हूँ जब कुछ चोर शर्तों को पूरा करने के लिए अलग-अलग मान जोड़ते हैं, या संभवतः अलग-अलग मूल्य जोड़ते हैं? अन्यथा निश्चित रूप से प्रत्येक काउंटर का मूल्य हमेशा 1 होगा?

यह कहा गया है कि, सबसे आसान समाधान मैं सोच सकता हूं कि केवल तीन लूप मानों के टुपल पर एक एकल निर्देश तैयार किया जाए। इस तरह उदाहरण कुछ के लिए:

dict(((a,b,c),1) for a in A for b in B for c in C) 

लेकिन जैसा कि मैंने कहा, यह सिर्फ प्रत्येक काउंटर में आप 1 देने के लिए जा रहा है। आप कुछ शर्त या समारोह कॉल कि एक, और के मूल्यों के आधार पर और अधिक उपयुक्त कुछ रिटर्न के साथ ऊपर अभिव्यक्ति में बदलना भी होगा।

0

मैं एक ऐसी ही जरूरत थी, और निम्न बनाया:

import json 

from collections import defaultdict 


class NestedDefaultDict(defaultdict): 
    def __init__(self, depth, default=int, _root=True): 
     self.root = _root 
     self.depth = depth 
     if depth > 1: 
      cur_default = lambda: NestedDefaultDict(depth - 1, 
                default, 
                False) 
     else: 
      cur_default = default 
     defaultdict.__init__(self, cur_default) 

    def __repr__(self): 
     if self.root: 
      return "NestedDefaultDict(%d): {%s}" % (self.depth, 
                defaultdict.__repr__(self)) 
     else: 
      return defaultdict.__repr__(self) 


# Quick Example 
core_data_type = lambda: [0] * 10 
test = NestedDefaultDict(3, core_data_type) 
test['hello']['world']['example'][5] += 100 
print test 
print json.dumps(test) 

# Code without custom class. 
test = defaultdict(lambda: defaultdict(lambda: defaultdict(core_data_type))) 
test['hello']['world']['example'][5] += 100 
print test 
print json.dumps(test) 

अगर मैं अंत में इस पर अद्यतन करने मैं भी एक सार बना लिया है: https://gist.github.com/KyleJamesWalker/8573350

संबंधित मुद्दे

 संबंधित मुद्दे