पायथन: इंडेक्स सेट के आधार पर सूची से सबसेट का चयन करें


98

मेरे पास कई सूचियाँ हैं जिनमें सभी समान प्रविष्टियाँ हैं (प्रत्येक एक वस्तु संपत्ति को निर्दिष्ट करती है):

property_a = [545., 656., 5.4, 33.]
property_b = [ 1.2,  1.3, 2.3, 0.3]
...

और एक ही लंबाई के झंडे के साथ सूची

good_objects = [True, False, False, True]

(जो आसानी से एक समान सूचकांक सूची के साथ प्रतिस्थापित किया जा सकता है:

good_indices = [0, 3]

सबसे आसान तरीका है नई सूची तैयार करने के लिए क्या है property_asel, property_bsel... जो होते हैं केवल मूल्यों से या तो संकेत दिया Trueप्रविष्टियों या सूचकांक?

property_asel = [545., 33.]
property_bsel = [ 1.2, 0.3]

जवाबों:


126

आप बस सूची समझ का उपयोग कर सकते हैं :

property_asel = [val for is_good, val in zip(good_objects, property_a) if is_good]

या

property_asel = [property_a[i] for i in good_indices]

उत्तरार्द्ध तेजी से होता है क्योंकि वहाँ good_indicesकी लंबाई से कम होते हैं property_a, यह मानते हुए कि good_indicesऑन-द-फ्लाई उत्पन्न होने के बजाय पूर्वनिर्मित हैं।


संपादित करें : पहला विकल्प itertools.compressपायथन 2.7 / 3.1 के बाद से उपलब्ध के बराबर है । @ गैरी केर का जवाब देखें ।

property_asel = list(itertools.compress(property_a, good_objects))

1
@ फ़फ़न: हाँ। पाइथन 2 पर बहुत कुछ होता है ( इसके बजाय itertools.izip का उपयोग करें ), पाइथन 3 पर इतना नहीं। ऐसा इसलिए है क्योंकि zipपाइथन 2 में एक नई सूची बनेगी , लेकिन पायथन 3 पर यह सिर्फ एक (आलसी) जेनरेटर लौटाएगा।
kennytm

ठीक है, इसलिए मुझे आपके 2 प्रस्ताव पर फिर से अड़ जाना चाहिए, क्योंकि इससे मेरे कोड का केंद्रीय हिस्सा बन जाता है।
फेनफंडाचटिजिग जूल

4
@ 85: आपको प्रदर्शन की चिंता क्यों है? आपको जो करना है, उसे लिखें, अगर यह धीमा है, तो बाधाओं को खोजने के लिए परीक्षण करें।
गैरी केर

1
@PreludeAndFugue: यदि दो समतुल्य विकल्प हैं, तो यह जानना अच्छा है कि कौन सा तेज़ है, और उस एक का उपयोग करें।
फेनफुंडचट्ज़िग

1
आप पहले उदाहरण में from itertools import izipइसके बजाय बस उपयोग और उपयोग कर सकते हैं zip। यही कारण है कि एक पुनरावृत्ति करता है, वही अजगर 3.
क्रिस बी।

28

मुझे 2 विकल्प दिखाई देते हैं।

  1. सुन्न का उपयोग करना:

    property_a = numpy.array([545., 656., 5.4, 33.])
    property_b = numpy.array([ 1.2,  1.3, 2.3, 0.3])
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = property_a[good_objects]
    property_bsel = property_b[good_indices]
  2. सूची समझ का उपयोग करना और इसे ज़िप करना:

    property_a = [545., 656., 5.4, 33.]
    property_b = [ 1.2,  1.3, 2.3, 0.3]
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = [x for x, y in zip(property_a, good_objects) if y]
    property_bsel = [property_b[i] for i in good_indices]

2
जब से ओपी सूचियों में संख्याओं को संग्रहित करना चाहता है, तब से Numpy का उपयोग करना एक अच्छा सुझाव है। एक द्वि-आयामी सरणी और भी बेहतर होगी।
फिलिप

यह भी एक अच्छा सुझाव है क्योंकि यह R के उपयोगकर्ताओं के लिए बहुत परिचित वाक्यविन्यास होगा, जहां इस तरह का चयन बहुत शक्तिशाली है, खासकर जब नेस्टेड और / या बहुआयामी हो।
थॉमस ब्राउन

[property_b[i] for i in good_indices]बिना उपयोग के लिए एक अच्छा हैnumpy
इल्या रुसिन

16

बिल्ट इन फंक्शन जिप का इस्तेमाल करें

property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]

संपादित करें

सिर्फ 2.7 के नए फीचर्स को देख रहे हैं। अब itertools मॉड्यूल में एक फ़ंक्शन है जो उपरोक्त कोड के समान है।

http://docs.python.org/library/itertools.html#itertools.compress

itertools.compress('ABCDEF', [1,0,1,0,1,1]) =>
  A, C, E, F

1
मैं itertools.compressयहाँ के उपयोग से अभिभूत हूँ । सूची समझ बहुत अधिक पठनीय है, बिना इस बात को खोदे कि हेक कम्प्रेस्स क्या कर रहा है।
पॉलएमसीजी

5
हम्म, मैं बहुत अधिक पठनीय का उपयोग कर कोड ढूंढता हूं :) शायद मैं पक्षपाती हूं, क्योंकि यह वही है जो मैं चाहता हूं।
फेनफंडाचटिजिग

8

यह मानते हुए कि आपके पास केवल वस्तुओं की सूची और सही / आवश्यक सूचकांकों की सूची है, यह सबसे तेज़ होना चाहिए:

property_asel = [ property_a[index] for index in good_indices ]

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

good_indices = [ index for index, item in enumerate(good_objects) if item ]

यह प्रत्येक आइटम को good_objects (enumerate के साथ इसके सूचकांक को याद करते हुए) के माध्यम से प्रसारित करता है और केवल उन सूचकांकों को लौटाता है जहां आइटम सत्य है।


किसी को भी सूची की समझ नहीं मिल रही है, यहाँ एक अंग्रेजी गद्य संस्करण है जिसमें बोल्ड पर प्रकाश डाला गया है:

सूची के लिए सूचकांक के हर समूह सूचकांक, आइटम है कि मौजूद है में एक गणना की अच्छी वस्तुओं , अगर (जहां) आइटम यह सच है


0

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

from numpy import *
property_a = array([545., 656., 5.4, 33.])
property_b = array([ 1.2,  1.3, 2.3, 0.3])
good_objects = [True, False, False, True]
good_indices = [0, 3]
property_asel = property_a[good_objects]
property_bsel = property_b[good_indices]

नेम्पी ने मटलब / स्किलाब की नकल करने की कोशिश की, लेकिन यह एक लागत पर आता है: आपको प्रत्येक सूची को "सरणी" कीवर्ड के साथ घोषित करने की आवश्यकता है, कुछ ऐसा जो आपकी स्क्रिप्ट को अधिभारित करेगा (यह समस्या मतलूब / सिलाब के साथ मौजूद नहीं है)। ध्यान दें कि यह समाधान संख्या के सरणियों तक सीमित है, जो आपके उदाहरण में मामला है।


3
प्रश्न में कहीं भी वह नुम्पी का उल्लेख नहीं करता है - नम्पी बनाम मतलाब पर अपनी राय व्यक्त करने की आवश्यकता नहीं है। पायथन लिस्ट में NumPy सरणियों के समान नहीं हैं , भले ही वे दोनों मोटे तौर पर वैक्टर के अनुरूप हों। (पायथन लिस्टें Matlab सेल सरणियों की तरह हैं - प्रत्येक तत्व का एक अलग डेटा प्रकार हो सकता है। कुछ अनुकूलन को सक्षम करने के लिए NumPy सरणियाँ अधिक प्रतिबंधित हैं)। आप पायथन द्वारा निर्मित filterया बाहरी पुस्तकालय के माध्यम से अपने उदाहरण के समान सिंटैक्स प्राप्त कर सकते हैं pandas। यदि आप भाषाओं की अदला-बदली करने जा रहे हैं, तो आप R को भी आज़मा सकते हैं, लेकिन यह वह नहीं है जो सवाल पूछ रहा है
लिवियस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.