2014-10-31 11 views
10

मैं एक विधि है कि एक सूची लेने के लिए और एक वस्तुपायथन: स्थानीय समझ को सूची समझ में कैसे सेट करें?

# input a list, returns an object 
def map_to_obj(lst): 
    a_list = f(lst) 
    return a_list[0] if a_list else None 

मैं एक सूची है कि सभी मैप किया तत्वों कि None नहीं करतीं प्राप्त करना चाहते वापसी की है।

इस तरह

:

v_list = [v1, v2, v3, v4] 

[map_to_obj(v) for v in v_list if map_to_obj(v)] 

लेकिन यह सूची समझ में दो बार map_to_obj विधि कॉल करने के अच्छा नहीं लगता है।

क्या सूची समझ में स्थानीय चर रखने का कोई तरीका है ताकि बेहतर प्रदर्शन हो सके?

या क्या संकलक स्वचालित रूप से इसे अनुकूलित करता है?

यहाँ मैं क्या चाहते है:

(sml like) 
[let mapped = map_to_obj(v) in for v in v_list if mapped end] 

उत्तर

33

नेस्टेड सूची समझ का उपयोग करें:

[x for x in [map_to_obj(v) for v in v_list] if x]

या बेहतर अभी भी, एक चारों ओर एक सूची समझ जनरेटर अभिव्यक्ति:

[x for x in (map_to_obj(v) for v in v_list) if x]

+3

यह एक अच्छा जवाब है। उत्तर में प्रश्न चिह्न नहीं होना चाहिए। – Paul

+0

यह एक अच्छा जवाब है, और निश्चित रूप से यह [behzad] (http://stackoverflow.com/users/625914/behzad-nouri) जैसा है, 'मानचित्र' और '' के स्थान पर सूची समझ के साथ फिल्टर' ... मैं ऊपर उठने जा रहा हूं क्योंकि मुझे पसंद आया [झूठ बोलना कुत्ता] (http: // stackoverflow।कॉम/उपयोगकर्ता/4134826/झूठ बोलने वाले) एल-सी के संदर्भ में 'फ़िल्टर' का अनुवाद किया गया है, लेकिन ओपी उन उत्तरों में से एक को स्वीकृति दे सकता है क्योंकि दोनों ठीक, उपयोगी उत्तर हैं। – gboffi

+2

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

3

आप अजगर में निर्मित filter का उपयोग करके फिर से गणना से बच सकते हैं:

list(filter(lambda t: t is not None, map(map_to_obj, v_list))) 
+0

लेकिन यह सूची को दो बार फिर से चलाता है ... –

+0

क्या कोई एक पुनरावृत्ति समाधान है? –

+0

@ हाओटान पायथन 3 में नहीं; पायथन 3 में, 'नक्शा' एक नक्शा वस्तु को एक सूची नहीं देता है, और 'फ़िल्टर' फ़िल्टर ऑब्जेक्ट देता है; इसलिए, यह इंटरमीडिएट सूचियों के बिना कार्यों को _chain_ करेगा। –

0

सूची comprehensions साधारण मामलों के लिए ठीक हैं, लेकिन कभी कभी एक सादे पुराने for पाश सरल समाधान है:

other_list = [] 
for v in v_list: 
    obj = map_to_obj(v) 
    if obj: 
     other_list.append(obj) 

अब अगर आप वास्तव में एक सूची कंप्यूटर अनुप्रयोग चाहते हैं और न

import itertools as it 
result = list(it.ifilter(None, it.imap(map_to_obj, v_list))) 
: एक tmp सूची का निर्माण करना चाहते हैं, तो आप filter और map की इटरेटर संस्करणों का उपयोग कर सकते हैं

या बस अधिक:

import itertools as it 
result = filter(None, it.imap(map_to_obj, v_list))) 

इटरेटर संस्करणों एक अस्थायी सूची का निर्माण नहीं करते, वे आलसी मूल्यांकन का उपयोग करें।

def map_and_append(lst, v): 
    mapped = map_to_obj(v) 
    if mapped is not None: 
     lst.append(mapped) 
    return lst 

reduce(map_and_append, v_list, []) 

कैसे इस के प्रदर्शन के बारे:

0

मैं reduce उपयोग करने का एक तरीका खोज निकाला है?

+0

के कॉल ओवरहेड के कारण सूची की समझ आमतौर पर मानचित्र/फ़िल्टर से तेज होती है, आप अलग-अलग समाधानों के समय 'टाइमिट' मॉड्यूल का उपयोग कर सकते हैं, लेकिन आपका उपरोक्त स्निपेट एक है एक बहुत ही सरल चीज करने के लिए मनमाने ढंग से अतिसंवेदनशील तरीका - और मुझे संदेह है कि यह लूप या फ़िल्टर/इमेप समाधान के लिए सादे पुराने की तुलना में या तो तेज या अधिक अंतरिक्ष-कुशल होगा ... –

+0

@ ब्रूनो मुझे आपकी «अतिसंवेदनशील» पसंद है! – gboffi

+0

यदि मैं कोई इटारटोल जवाब नहीं देखता हूं, तो प्रदर्शन के बावजूद, मुझे लगता है कि [झूठ बोलने वाला कुत्ता] [http://stackoverflow.com/a/26672589/2749397) इरादे का सबसे अभिव्यक्तिपूर्ण है, और इसलिए सबसे अधिक पढ़ने योग्य है। और प्रदर्शन के बारे में क्या? ठीक है, मुझे नहीं पता कि आप अपने 'एफ (एलएसटी) कॉल में कितना सीपीयू खर्च करते हैं, लेकिन' किसी का भी एक तरीका या किसी अन्य को हटाने से पूरी तस्वीर को बदलने की संभावना नहीं है। – gboffi

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