2015-06-23 9 views
12

कल्पना कीजिए कि मैं tuples के एक आदेश सूची है:सूची चयन रोकना?

s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)] 

एक पैरामीटर X देखते हुए, मैं सभी tuples एक पहला तत्व बराबर या X अप करने के लिए, लेकिन पहले टपल सहित नहीं से अधिक है का चयन करना चाहते है कि दूसरे तत्व के रूप में -1 है।

उदाहरण के लिए, यदि X = 3, मैं सूची का चयन करने [(3,0), (4,0)]

एक विचार मैं था चाहते हैं:

E = min (x [0] for x in s if (x [0] >= X) and (x [1] == -1)) 

साथ कट ऑफ कुंजी प्राप्त करें तब X के बीच कुंजी के साथ तत्वों का चयन और E:

R = [x for x in s if X <= x [0] < E] 

मुझे देता है यही कारण है कि मैं आर में चाहते हैं, लेकिन यह असली लगती है ly अक्षम, दो टेबल स्कैन शामिल है। मैं इसे लूप में कर सकता था, कुंजियों को बहुत छोटा कर देता था, और ब्रेक तोड़ता था जब मैंने पहली ब्लॉकिंग टुपल मारा था। लेकिन सूची चयन की तुलना में कुत्ते की तरह रनों के लिए।

क्या ऐसा करने के लिए एक सुपर-कुशल, पायथन-एस्क्यू (2.7) तरीका है?

उत्तर

26

आप बस एक जनरेटर अभिव्यक्ति के रूप में सूची से tuples फ़िल्टर कर सकते हैं और फिर आप मान इस

>>> s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)] 
>>> from itertools import takewhile 
>>> X = 3 
>>> list(takewhile(lambda x: x[1] != -1, (item for item in s if item[0] >= X))) 
[(3, 0), (4, 0)] 

की तरह, जब आप पहली बार टपल जिसका दूसरा तत्व -1 है मिल जनरेटर अभिव्यक्ति से लेना बंद कर सकते हैं यहां, जनरेटर अभिव्यक्ति, (item for item in s if item[0] >= X) मांग पर एक-एक करके मूल्य प्रदान करेगा, (वे सभी एक बार में उत्पन्न नहीं होते हैं, इसलिए हम यहां स्मृति को सहेजते हैं) जो X से अधिक या बराबर हैं।

फिर, हम उस जनरेटर अभिव्यक्ति से मूल्य लेते हैं, केवल तब तक जब तक हम एक tuple नहीं पाते हैं जिसका दूसरा तत्व -1 के बराबर नहीं है, itertools.takewhile के साथ।

+9

आपका जवाब सुंदर ढंग से मेरी हर चिंता संतुष्ट करता है। मैं खुशी से रोता हूँ। –

1

यहाँ takewhile एक जनरेटर अभिव्यक्ति के हिस्से के रूप लागू करने के लिए एक से थोड़ा hacky है:

def stop(): raise StopIteration 

result = (
    stop() if item[1] == -1 else 
    item 
    for item in s 
    if item[0] >= X 
) 

या अलग शब्दों के साथ:

def until(cond): 
    if cond: raise StopIteration 
    return True 

result = (
    item for item in s 
    if item[0] >= X 
    and until(item[1] == -1) 
) 
+0

दिलचस्प बात यह है कि समान दृष्टिकोण सूची समझ में काम नहीं करेगा, क्योंकि 'if' खंड समझ/जनरेटर आंतरिक कोड द्वारा 'रोकथाम' हैंडलिंग के बाहर है, इसलिए अपवाद प्रचारित करता है। (जेनरेटर के साथ यह भी करता है, लेकिन यह उस कोड द्वारा स्वाभाविक रूप से संभाला जाता है जो * जनरेटर का उपयोग करता है)। यह टिप्पणी उन लोगों के संभावित लाभ के लिए है जो इस तकनीक को समझने के लिए लागू करने की कोशिश करेंगे और जैसे ही मैं थे। :) – atzz

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