2009-12-29 16 views
33

यह निम्न से संबंधित है: (अजगर कोड में)मुझे लूप लूप के बजाय मानचित्र का उपयोग कब करना चाहिए?

for i in object: 
    doSomething(i) 

बनाम

map(doSomething, object) 

दोनों को समझने के लिए आसान है, और कम कर रहे हैं, लेकिन वहाँ किसी भी गति का अंतर है? अब, अगर ऐसा कुछ है तो वापसी मूल्य था, हमें यह जांचने की आवश्यकता थी कि इसे मानचित्र से एक सूची के रूप में वापस कर दिया जाएगा, और लूप के लिए हम या तो अपनी खुद की सूची बना सकते हैं या एक समय में एक जांच सकते हैं।

for i in object: 
    returnValue = doSomething(i) 
    doSomethingWithReturnValue(returnValue) 

बनाम

returnValue = map(doSomething, object) 
map(doSomethingWithReturnValue, returnValue) 

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

जो मैं खोज रहा हूं वह एक परिदृश्य है जहां मैपिंग फ़ंक्शन वास्तव में प्रदर्शन, पठनीयता, रखरखाव, या कार्यान्वयन की गति में लूप के लिए अच्छी तरह से किए गए की तुलना में चमकता है। अगर जवाब वास्तव में कोई बड़ा अंतर नहीं है तो मैं जानना चाहता हूं कि अभ्यास में लोग एक या दूसरे का उपयोग करते हैं या यदि यह वास्तव में पूरी तरह से मनमानी है और आपके संस्थान के आधार पर कोडिंग मानकों द्वारा निर्धारित किया गया है।

धन्यवाद!

+2

आप मानचित्र के बजाय सूची/शब्दकोश/सेट समझ या जेनरेटर का उपयोग कर सकते हैं - क्या कुछ करता है() करता है। –

+2

प्रदर्शन प्रारंभिक tweak करने की कोशिश मत करो। मैं हमेशा सबसे अच्छा पठनीय विकल्प लेता हूं। बाद में रनटाइम दिखाएगा कि शोस्टॉपर प्रदर्शन एक मुद्दा है और आपने गति या संसाधन-उपयोग में सुधार किया है। –

उत्तर

22

map उपयोगी है जब आप एक पुनरावर्तनीय प्रत्येक आइटम पर फ़ंक्शन को लागू करना चाहते हैं और परिणामों की एक सूची वापस कर सकते हैं। लूप का उपयोग करने और सूची बनाने से यह सरल और अधिक संक्षिप्त है।

for अन्य स्थितियों के लिए अक्सर अधिक पठनीय होता है, और लिस्प में बहुत सारे पुनरावृत्ति संरचनाएं होती हैं जो मूल रूप से मैक्रोज़ और मानचित्र का उपयोग करके लिखी जाती थीं। तो, ऐसे मामलों में जहां map फिट नहीं है, for लूप का उपयोग करें।

सिद्धांत रूप में, यदि हमारे पास एक कंपाइलर/दुभाषिया था जो एकाधिक सीपीयू/प्रोसेसर का उपयोग करने के लिए पर्याप्त स्मार्ट था, तो map को तेजी से कार्यान्वित किया जा सकता था क्योंकि प्रत्येक आइटम पर अलग-अलग संचालन समानांतर में किया जा सकता था। मुझे नहीं लगता कि वर्तमान में यह मामला है।

+0

PLINQ (सी #) हालांकि ऐसा कर सकता है। –

+12

पिछले काल क्यों? लिस्प जीवित और लात मार रहा है। – Svante

+3

असल में 'नक्शा' प्रदर्शन में प्रदर्शन के लिए 'थ्रेड' में भी होता है क्योंकि लूप सी में लिखा जाता है। स्पीड टेस्ट के लिए मेरी पोस्ट देखें। – iamamac

7

बस सूची समझ का उपयोग करें: वे अधिक पाइथनिक हैं। उनके पास जेनरेटर एक्सप्रेशन के समान वाक्यविन्यास भी है जो एक से दूसरे में स्विच करना आसान बनाता है। अपने कोड को py3k में कनवर्ट करते समय आपको कुछ भी बदलने की आवश्यकता नहीं है: map py3k में एक पुनरावर्तनीय लौटाता है और आपको अपना कोड समायोजित करना होगा।

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

0

संपादित: मुझे नहीं पता था कि map अजगर 3.0 के बाद itertools.imap बराबर होती है। तो यहां निष्कर्ष सही नहीं हो सकता है। मैं कल पाइथन 2.6 पर परीक्षण फिर से चलाऊंगा और परिणाम पोस्ट करूंगा।

तो doSomething बहुत "छोटे" है, map for पाश या एक सूची-समझ की तुलना में बहुत तेजी से हो सकता है:

# Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on win32 

from timeit import timeit 

do = lambda i: i+1 

def _for(): 
    for i in range(1000): 
    do(i) 

def _map(): 
    map(do, range(1000)) 

def _list(): 
    [do(i) for i in range(1000)] 

timeit(_for, number=10000) # 2.5515936921388516 
timeit(_map, number=10000) # 0.010167432629884843 
timeit(_list, number=10000) # 3.090125159839033 

इसका कारण यह है map सी में लिखा है, जबकि for पाश और पायथन वर्चुअल मशीन में सूची-समझ चलती है।

+1

मुझे नहीं पता कि आप कहां से अपनी संख्या प्राप्त कर रहे हैं, लेकिन मेरे मामले में (पायथन 2.6) लूप के लिए लगभग 5% तेज है। आपका कोड भी सही नहीं है क्योंकि _list कम पुनरावृत्तियों करता है। आपके द्वारा प्राप्त किए गए विशाल मतभेद बताते हैं कि आपके सेटअप में कुछ गंभीरता से गलत है। – interjay

+0

यह सिर्फ हास्यास्पद है। आपके कोड बिल्कुल समान नहीं हैं। मेरा जवाब पढ़ें। यहां तक ​​कि मानचित्र वस्तु बनाम सूची dichotomy भी आपका कोड अलग है, यह वास्तव में एक शर्म की बात है कि आप इसे नहीं देखते हैं – SilentGhost

+0

क्षमा करें जब मैंने कोड कॉपी किया और प्रारूपण किया तो कुछ टाइपो त्रुटि हुई। मैं अपने कोर डुओ 4300 पीसी पर पायथन 3.1.1 चलाता हूं, 'मैप' अन्य दो महत्वपूर्ण रूप से धड़कता है। – iamamac

10

क्या आप टाइमिट मॉड्यूल से परिचित हैं? नीचे कुछ समय हैं। -s एक बार सेटअप करता है, और फिर आदेश looped और रिकॉर्ड किया गया सबसे अच्छा समय है।

1> python -m timeit -s "L=[]; M=range(1000)" "for m in M: L.append(m*2)" 
1000 loops, best of 3: 432 usec per loop 

2> python -m timeit -s "M=range(1000);f=lambda x: x*2" "L=map(f,M)" 
1000 loops, best of 3: 449 usec per loop 

3> python -m timeit -s "M=range(1000);f=lambda x:x*2" "L=[f(m) for m in M]" 
1000 loops, best of 3: 483 usec per loop 

4> python -m timeit -s "L=[]; A=L.append; M=range(1000)" "for m in M: A(m*2)" 
1000 loops, best of 3: 287 usec per loop  

5> python -m timeit -s "M=range(1000)" "L=[m*2 for m in M]" 
1000 loops, best of 3: 174 usec per loop 

नोट करें कि वे पिछले दो को छोड़कर सभी समान हैं। यह फंक्शन कॉल (एल। एपेंड, या एफ (एक्स)) है जो समय को गंभीर रूप से प्रभावित करता है। # 4 में L.append लुकअप सेटअप में एक बार किया गया है। # 5 में कोई फंक्शन कॉल के साथ एक सूची COMP का उपयोग किया जाता है।

+0

मुझे लगता है कि आप मेरी पोस्ट का जिक्र कर रहे हैं। हां, मुझे गंभीर समस्या मिली है कि 'मैप' पीई 3 के में इटरेटर लौटाता है, लेकिन मुझे नहीं लगता कि 'टाइमिट' के साथ कुछ भी गलत है, 'रेंज' रिटर्न इटरेटर्स इसलिए सेटअप चरण में थोड़ा प्रभाव नहीं डालता है। – iamamac

+0

> पायथन 3-एम टाइमिट "[मीटर में एम के लिए मीटर (1000)]" 10000 लूप, 3: 114 उपयोगक प्रति लूप > पायथन 3-एम टाइमिट-एम = सूची (रेंज (1000)) "[ एम में एम के लिए एम] " 10000 लूप, 3: 83 usec प्रति लूप केवल एक बार सूची बनाने में महत्वपूर्ण अंतर है। –

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