2013-09-01 5 views
10

ठीक है, क्षमा करें अगर मेरी समस्या थोड़ा मोटा लगता है। मैं इसे एक लाक्षणिक तरीके से समझाने की कोशिश करूंगा, मुझे उम्मीद है कि यह संतोषजनक है।पायथन में बड़ी संख्या में मूल्यों को बढ़ाने का सबसे प्रभावी तरीका क्या है?

10 बच्चे।
5 बक्से।
प्रत्येक बच्चा तीन बक्से चुनता है।
प्रत्येक बॉक्स खोला गया है:
- यदि इसमें कुछ शामिल है, इस बच्चे को चयनित सभी बच्चे 1 बिंदु
- अन्यथा, कोई भी बिंदु नहीं मिलता है।

मेरा प्रश्न जो मैंने बोल्ड में रखा है उसके बारे में है। क्योंकि मेरे कोड में, बहुत सारे बच्चे और बहुत से बक्से हैं।

children = {"child_1" : 0, ... , "child_10": 0} 

gp1 = ["child_3", "child_7", "child_10"] #children who selected the box 1 
... 
gp5 = ["child_2", "child_5", "child_8", "child_10"] 

boxes = [(0,gp1), (0,gp2), (1,gp3), (1,gp4), (0,gp5)] 

for box in boxes: 
    if box[0] == 1: #something inside 
     for child in box[1]: 
      children[child] += 1 

मैं के बारे में मुख्य रूप से चिंता पाश कि प्रत्येक बच्चे को एक अतिरिक्त अंक प्रदान करती है के लिए:

वर्तमान में, मैं इस प्रकार आगे बढ़ें। क्योंकि मेरे अंतिम कोड में, मेरे पास कई बच्चे हैं, मुझे डर है कि ऐसा करने से कार्यक्रम धीमा हो जाएगा।

क्या एक ही समूह के सभी बच्चों के लिए एक और अधिक प्रभावी तरीका हो सकता है?

+1

यह उचित रूप से कुशल दिखता है। क्या आप जानते हैं कि यह बहुत धीमी है? – zch

+0

मुझे लगता है कि पूरी प्रक्रिया कई बार दोहराई जाती है। बक्से या समूह अक्सर बदलते हैं? – user2722968

+0

"कितने, कई बच्चे" हैं? एक चीज जो आप कर सकते हैं वह 'बच्चों' शब्दकोष के बजाय 'संग्रह। काउंटर' का उपयोग करना है, विशेष रूप से जिस तरह से आप इसे शुरू कर रहे हैं (लेकिन आप बच्चों की सूची के आधार पर 'dict' समझ' का भी उपयोग कर सकते हैं। –

उत्तर

5
  1. तारों के रूप में नहीं, विन्यास में, सूचकांक के रूप में बच्चों का प्रतिनिधित्व करते हैं:

    अंत में, आप कैश फायदा उठाने के लिए अपने countBoxesForChild समारोह संशोधित कर सकते हैं तो फिर

    childrenScores = [0] * 10 
    gp1 = [2,6,9] # children who selected box 1 
    ... 
    gp5 = [1,4,7,9] 
    
    boxes = [(0,gp1), (0,gp2), (1,gp3), (1,gp4), (0,gp5)] 
    
  2. , आप कर सकते हैं childrenScores एक NumPy सरणी के रूप में की दुकान है और उपयोग उन्नत अनुक्रमण:

    childrenScores = np.zeros(10, dtype=int) 
    ... 
    for box in boxes: 
        if box[0]: 
         childrenScores[box[1]] += 1 # NumPy advanced indexing 
    

    यह अभी भी कहीं न कहीं एक पाश शामिल है, लेकिन पाश बजाय NumPy अंदर गहरा है, जो एक सार्थक speedup प्रदान करना चाहिए।

+0

दुर्भाग्य से, मुझे बच्चों के बारे में कुछ जानकारी भी जाननी है। मान लीजिए, उदाहरण के लिए, उनकी उम्र और आकार। इसलिए, मेरे असली चर "1_12_170" (number_age_size) रूप में हैं। यही वह है जो मैं उन्हें स्ट्रिंग के रूप में रखता हूं और मैं उन्हें संख्याओं में परिवर्तित नहीं कर सकता। – Delgan

+0

@ user2737736, आप उन्हें संख्याओं में परिवर्तित कर सकते हैं और वे संरचना की अनुक्रमणिका हो सकते हैं जहां अतिरिक्त जानकारी संग्रहीत की जाती है (उदाहरण के लिए डेटाबेस तालिका की आईडी)। –

+0

@ user2737736: इस मामले में, अपनी आयु और आकार के बारे में जानकारी को एक अलग संरचना (उदाहरण के लिए 'बच्चों के उदाहरणों की एक सूची) में संग्रहीत करें, फिर से उनके आईडी द्वारा अनुक्रमित करें। – nneonneo

0

एक तरफ या दूसरा, आप बच्चों पर लूपिंग करने जा रहे हैं, और आपका उत्तर उन बच्चों पर लूपिंग से बचने के लिए प्रतीत होता है जिन्हें कोई अंक नहीं मिलता है।

यह हो सकता है हो सकता है थोड़ा तेजी से फिल्टर का उपयोग करने के लिए या itertools.ifilter बक्से कि उन में कुछ है लेने के लिए:

import itertools 

... 

for box in itertools.ifilter(lambda x: x[0], boxes): 
    for child in box[1] 
     children[child] += 1 
2

केवल गति को मैं के बारे में सोच सकते हैं कि NumPy सरणी का उपयोग करें और स्ट्रीम करने के लिए है योग संचालन

children[child] += np.ones(len(children[child])) 

आपको ऑपरेशन को बेंचमार्क करना चाहिए और देखें कि यह आपके व्यावसायिक मामले के लिए बहुत धीमा है या नहीं।

+1

'बच्चे [बच्चे] + = 1' भी काम करेगा। – mattexx

1

मैं

gpX सूचियों में क्या होगा "बच्चे का नाम" बचाने नहीं है (उदा "child_10"), लेकिन अंक के बच्चे की संख्या के लिए एक संदर्भ बचाने के।

कि

तथ्य यह है कि सूचियों अजगर में वस्तुओं रहे हैं का उपयोग कैसे करना है, आप कर सकते हैं: children = {"child_0": [0], "child_1": [0], ...} और इतने पर:

  1. बदलें बच्चों dict तरह देखने के लिए।
  2. जब आप समूह को असाइन करते हैं, तो कुंजी असाइन न करें लेकिन मान (उदा। gp1.append(children["child_0"])) असाइन करें।
  3. लूप को तब दिखाना चाहिए: for child in box[1]: child[0]+=1। यह होगाchildren dict अद्यतन करें।

संपादित करें:

क्यों इस तेजी से है: क्योंकि आप हिस्सा जहां children[child], जो महंगा हो सकता है के लिए खोज को छोड़ दें।

यह तकनीक काम करता है क्योंकि एक उत्परिवर्तनीय प्रकार में योग को संग्रहित करके, और उन मानों को समूह सूचियों में जोड़कर, दोनों मूल्य मान और प्रत्येक बॉक्स की सूची मान दोनों सूची प्रविष्टियों को इंगित करेंगे, और एक बदलना दूसरे को बदल देगा ।

+0

यह एक बहुत चालाक तकनीक है! ओपी के लिए मेरी एकमात्र चेतावनी यह होगी कि अंत तक अनुकूलन को सहेजना सबसे अच्छा होता है, जब आप यह समझ सकते हैं कि आपके कोड के कौन से हिस्से अस्वीकार्य रूप से धीमे हैं। कोड के एक हिस्से को अनुकूलित करने में व्यतीत समय जो स्वीकार्य रूप से तेज़ चलता है वह समय बर्बाद हो जाता है। –

+0

मुझे यह देखने में दिलचस्पी होगी कि क्या बच्चा [0] 'बच्चों के नाम से वास्तव में तेज़ है। केवल एक तत्व के साथ एक सूची तक पहुंचना तेज होगा, लेकिन सैद्धांतिक रूप से शब्दकोश लुकअप को शब्दकोश के आकार के बावजूद समान प्रदर्शन करना चाहिए। – nmclean

0

यदि आपको प्रत्येक बच्चे के लिए अंक की संख्या तुरंत प्रिंट करने की आवश्यकता नहीं है, तो आप इसकी मांग पर गणना कर सकते हैं, इस प्रकार समय बचा सकते हैं। यह अगर आप केवल यह है कि कितने अंक हैं के लिए हर अब और फिर एक बच्चे क्वेरी करने के लिए की जरूरत है मदद कर सकता है। आप प्रत्येक परिणाम कैश के रूप में आप प्राप्त है, तो आप इसे फिर से अगली बार जब आप इसकी आवश्यकता की गणना के बारे में मत जाओ कर सकते हैं।

सबसे पहले, आप को पता है जो समूहों में एक बच्चे के अंतर्गत आता है की आवश्यकता होगी। हम तो जैसे इस जानकारी नक्शे के रूप में हम childToGroupsMap फोन करता हूँ, बक्से यह के अंतर्गत आता है पकड़े जो एक सरणी के लिए प्रत्येक बच्चे को मैप कर देंगे संग्रहीत करेंगे,:

childToGroupsMap = {} 
for child in children: 
    childToGroupsMap[child[0]] = [] 
for box in boxes: 
    for child in box[1]: 
     if (box[1] not in childToGroupsMap[child]): 
      childToGroupsMap[child].append(box[1]) 

इस बक्से को बच्चों से रिवर्स मानचित्र बनाता है।

यह भी एक बूलियन का प्रतिनिधित्व करने के लिए कि क्या इसे खोला गया है करने के लिए प्रत्येक बॉक्स के एक नक्शे के लिए मदद करेंगे:

boxToOpenedMap = {} 
for box in boxes: 
    boxToOpenedMap[box[1]] = box[0] 

अब, किसी व्यक्ति प्रश्नों कितने अंक एक बच्चा है, आप में से प्रत्येक के माध्यम से जा सकते हैं

def countBoxesForChild(child): 
    points = 0 
    for box in childToGroupsMap[child] 
     if boxToOpenedMap[box] == 1: 
      points += 1 
    return points 

इस बेहतर बनाने के लिए, आप कर सकते हैं c: बॉक्स यह करने के लिए (childToGroupsMap का उपयोग कर, निश्चित रूप से), और बस गिनती कैसे उन बक्से के कई नक्शे boxes में 1 को मैप किया गया है अंतर्गत आता है दर्द अंकों की जिसके परिणामस्वरूप संख्या। एक नक्शा इतना की तरह बनाओ:

childToPointsCalculated = {} 
for child in children: 
    childToPointsCalculated[child[0]] = -1 

-1 कहाँ अर्थ है हम अभी तक पता नहीं है कि कितने अंक इस बच्चे है।

def countBoxesForChild(child): 
    if childToPointsCalculated[child] != -1 
     return childToPointsCalculated[child] 

    points = 0 
    for box in childToGroupsMap[child] 
     if boxToOpenedMap[box] == 1: 
      points += 1 
    childToPointsCalculated[child] = points 
    return points 
+3

'++' पायथन में कानूनी नहीं है। – nneonneo

+0

@nneonneo, धन्यवाद !, मैं हाल ही में भाषाओं के बीच जुगल कर रहा हूं। –

1

दो सामान्य अंक:

(1) क्या आप हमें बता चुके के आधार पर, वहाँ मामूली प्रदर्शन अनुकूलन पर अपनी ऊर्जा ध्यान केंद्रित करने का कोई कारण नहीं। आपका समय आपकी डेटा संरचनाओं को कम अजीब और अधिक संवादात्मक बनाने के तरीकों के बारे में सोचने में बेहतर होगा। पारस्परिक डिक्ट्स, सूचियों और टुपल्स का एक समूह जल्दी से बनाए रखना मुश्किल हो जाता है। एक विकल्प के लिए, नीचे उदाहरण देखें।

(2) खेल डिजाइनर के रूप में, आप समझते हैं कि घटनाओं के लिए एक निश्चित अनुक्रम का पालन करें: पहले बच्चों को अपनी बॉक्स का चयन करें, और बाद में उन्हें पता चलता है कि क्या वे उनके लिए अंक मिलता है। लेकिन आपको इसे इस तरह लागू करने की ज़रूरत नहीं है। एक बच्चा एक बॉक्स चुन सकता है और तुरंत अंक प्राप्त कर सकता है (या नहीं)। अगर इस तरह के परिणामों के बारे में बच्चे की अज्ञानता को संरक्षित करने की आवश्यकता है, तो इस तरह की अज्ञानता पर निर्भर आपके एल्गोरिदम के कुछ हिस्सों को आवश्यकतानुसार गुप्तता का पर्दाफाश कर सकते हैं। उपरोक्त: अपने बच्चों के माध्यम से लूप करने के लिए बॉक्स की आवश्यकता नहीं है, प्रत्येक को अंक प्रदान करना; इसके बजाय, बच्चों को तत्काल अंक प्रदान करें क्योंकि बक्से चुने जाते हैं।

import random 

class Box(object): 
    def __init__(self, name): 
     self.name = name 
     self.prize = random.randint(0,1) 

class Child(object): 
    def __init__(self, name): 
     self.name = name 
     self.boxes = [] 
     self.score = 0 
     self._score = 0 

    def choose(self, n, boxes): 
     bs = random.sample(boxes, n) 
     for b in bs: 
      self.boxes.append(b) 
      self._score += b.prize 

    def reveal_score(self): 
     self.score = self._score 

boxes = [Box(i) for i in range(5)] 
kids = [Child(i) for i in range(10)] 

for k in kids: 
    k.choose(3, boxes) 

# Later in the game ... 
for k in kids: 
    k.reveal_score() 
    print (k.name, k.score), '=>', [(b.name, b.prize) for b in k.boxes] 
संबंधित मुद्दे

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