स्पष्ट रूप से सूची या टपल से आइटम का चयन करें


120

मेरे पास निम्नलिखित पायथन सूची है (टपल भी हो सकती है):

myList = ['foo', 'bar', 'baz', 'quux']

मैं कह सकता हूं

>>> myList[0:3]
['foo', 'bar', 'baz']
>>> myList[::2]
['foo', 'baz']
>>> myList[1::2]
['bar', 'quux']

मैं स्पष्ट रूप से उन वस्तुओं को कैसे चुन सकता हूं जिनके सूचकांकों का कोई विशिष्ट पैटर्न नहीं है? उदाहरण के लिए, मैं चयन करना चाहता हूं [0,2,3]। या 1000 वस्तुओं की एक बहुत बड़ी सूची से, मैं चयन करना चाहता हूं [87, 342, 217, 998, 500]। क्या कुछ पायथन सिंटैक्स है जो ऐसा करता है? कुछ ऐसा दिखता है:

>>> myBigList[87, 342, 217, 998, 500]

1
यह एक डुप्लिकेट प्रतीत होता है। दूसरे प्रश्न में वोटों की संख्या अधिक है लेकिन ऐसा लगता है कि इसका समय के साथ बेहतर जवाब है।
अन्नानय

जवाबों:


149
list( myBigList[i] for i in [87, 342, 217, 998, 500] )

मैंने अजगर 2.5.2 के उत्तरों की तुलना की:

  • 19.7 usec: [ myBigList[i] for i in [87, 342, 217, 998, 500] ]

  • 20.6 usec: map(myBigList.__getitem__, (87, 342, 217, 998, 500))

  • 22.7 usec: itemgetter(87, 342, 217, 998, 500)(myBigList)

  • 24.6 usec: list( myBigList[i] for i in [87, 342, 217, 998, 500] )

ध्यान दें कि पायथन 3 में, 1 को 4 के समान ही बदल दिया गया था।


एक अन्य विकल्प numpy.arrayएक सूची या एक के माध्यम से अनुक्रमण की अनुमति देने के साथ शुरू करना होगा numpy.array:

>>> import numpy
>>> myBigList = numpy.array(range(1000))
>>> myBigList[(87, 342, 217, 998, 500)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> myBigList[[87, 342, 217, 998, 500]]
array([ 87, 342, 217, 998, 500])
>>> myBigList[numpy.array([87, 342, 217, 998, 500])]
array([ 87, 342, 217, 998, 500])

tupleउन लोगों के रूप स्लाइस हैं उसी तरह काम नहीं करता।


2
अधिमानतः एक सूची COMP के रूप में [myBigList[i] for i in [87, 342, 217, 998, 500]], लेकिन मुझे यह दृष्टिकोण सबसे अच्छा लगता है।
ज़ेके

@MedhatHelmy यह पहले से ही जवाब में है। तीसरे विकल्प का उपयोग from operator import itemgetterप्रारंभिक भाग में किया गया python -mtimeit
दान डी।

मुझे आश्चर्य है, सिर्फ एक भाषा डिजाइन के नजरिए से, myBigList[(87, 342, 217, 998, 500)]जब myBigListएक नियमित अजगर क्यों काम नहीं करता है list? जब मैं कोशिश करता हूं कि मुझे मिल जाए TypeError: list indices must be integers or slices, not tuple। यह समझ से बाहर टाइप करने की तुलना में इतना आसान होगा - क्या कोई भाषा डिजाइन / कार्यान्वयन मुद्दा शामिल है?
स्पार्क_स्प्रेड

@ sparc_spread, ऐसा इसलिए है क्योंकि listsपायथन में केवल पूर्णांक या स्लाइस स्वीकार किए जाते हैं। पूर्णांक पास करना सुनिश्चित करता है कि मौजूदा सूची से केवल एक आइटम पुनर्प्राप्त किया जाता है। एक स्लाइस को पास करना सुनिश्चित करता है कि इसका एक हिस्सा पुनर्प्राप्त किया जाता है, लेकिन एक टपल को पास करना एक डेटा-प्रकार ( tuple) को किसी अन्य डेटा-प्रकार ( list) के तर्क के रूप में पारित करने जैसा है जो कि वाक्यात्मक रूप से गलत है।
अमनब

48

इस बारे में क्या:

from operator import itemgetter
itemgetter(0,2,3)(myList)
('foo', 'baz', 'quux')

2
यह अब तक का सबसे सेक्सी है। उस operatorमॉड्यूल को प्यार करो!
2

10

यह बिल्ट-इन नहीं है, लेकिन यदि आप चाहें तो सूची का एक उपवर्ग बना सकते हैं, जो "इंडेक्स" के रूप में ट्यूपल्स लेता है:

class MyList(list):

    def __getitem__(self, index):
        if isinstance(index, tuple):
            return [self[i] for i in index]
        return super(MyList, self).__getitem__(index)


seq = MyList("foo bar baaz quux mumble".split())
print seq[0]
print seq[2,4]
print seq[1::2]

मुद्रण

foo
['baaz', 'mumble']
['bar', 'quux']

2
(+1) नीट हल! इस विस्तार के साथ, पायथन में एरे को संभालने के लिए बहुत अधिक आर या मैटलैब दिखना शुरू हो जाता है।
असद इब्राहिम

7

हो सकता है कि एक सूची समझ के क्रम में हो:

L = ['a', 'b', 'c', 'd', 'e', 'f']
print [ L[index] for index in [1,3,5] ]

पैदा करता है:

['b', 'd', 'f']

क्या यह वही है जिसको आप ढूंढ रहें थे।


6
>>> map(myList.__getitem__, (2,2,1,3))
('baz', 'baz', 'bar', 'quux')

आप अपना स्वयं का Listवर्ग भी बना सकते हैं जो ट्यूपल्स को तर्क का समर्थन करता है __getitem__यदि आप करना चाहते हैं myList[(2,2,1,3)]


हालांकि यह काम करता है यह आमतौर पर जादू चर को सीधे लागू करने के लिए एक अच्छा विचार नहीं है। आप सूची बोध या सहायक मॉड्यूल का उपयोग करके बेहतर हैं operator
2

@ जातिवाद: मुझे सम्मानपूर्वक असहमत होना है। यद्यपि यदि आप आगे अनुकूलता के बारे में चिंतित हैं (सार्वजनिक / निजी के विपरीत) तो मैं निश्चित रूप से देख सकता हूँ कि आप कहाँ से आ रहे हैं।
Ninjagecko

यहीं से आ रहा हूं। :) इसके बाद, यह एक ही कारण है कि इसका उपयोग len(myList)करना बेहतर है myList.__len__()
१२:२५ बजे १२:१२

एक रचनात्मक समाधान। मुझे नहीं लगता कि जादू चर को लागू करना एक बुरा विचार है। प्रोग्रामर प्रोग्रामिंग परिस्थितियों के आधार पर अपने पसंदीदा तरीके का चयन करता है।
याकूब CUI

2

मैं केवल इंगित करना चाहता हूं, यहां तक ​​कि आइटमगार्ड का सिंटैक्स वास्तव में साफ-सुथरा दिखता है, लेकिन बड़ी सूची पर प्रदर्शन करते समय यह थोड़े धीमा होता है।

import timeit
from operator import itemgetter
start=timeit.default_timer()
for i in range(1000000):
    itemgetter(0,2,3)(myList)
print ("Itemgetter took ", (timeit.default_timer()-start))

आइटमगेटर ने 1.065209062149279 लिया

start=timeit.default_timer()
for i in range(1000000):
    myList[0],myList[2],myList[3]
print ("Multiple slice took ", (timeit.default_timer()-start))

मल्टीपल स्लाइस में 0.6225321444745759 लिया गया


पहला स्निपेट, कृपया जोड़ें myList = np.array(range(1000000))अन्यथा आपको त्रुटि मिलेगी।
क्लाउड चो

1

एक अन्य संभावित समाधान:

sek=[]
L=[1,2,3,4,5,6,7,8,9,0]
for i in [2, 4, 7, 0, 3]:
   a=[L[i]]
   sek=sek+a
print (sek)

0

जैसे अक्सर जब आपके पास बूलियन सुन्न सरणी होती है जैसे mask

[mylist[i] for i in np.arange(len(mask), dtype=int)[mask]]

एक लंबोदर जो किसी भी अनुक्रम या np.array के लिए काम करता है:

subseq = lambda myseq, mask : [myseq[i] for i in np.arange(len(mask), dtype=int)[mask]]

newseq = subseq(myseq, mask)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.