पाइथोनिक तरीका एक बड़ी सूची में हर एनथ आइटम की सूची वापस करने के लिए


170

मान लें कि हमारे पास 0 से 1000 तक की संख्या है। क्या पहले और हर बाद की 10 वीं वस्तु की सूची बनाने के लिए एक पायथोनिक / कुशल तरीका है, अर्थात [0, 10, 20, 30, ... ]?

हां, मैं लूप के लिए इसका उपयोग कर सकता हूं, लेकिन मैं सोच रहा हूं कि क्या ऐसा करने के लिए कोई एनटर तरीका है, शायद एक लाइन में भी?

जवाबों:


289
>>> lst = list(range(165))
>>> lst[0::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]

ध्यान दें कि यह लूपिंग की तुलना में लगभग 100 गुना तेज है और प्रत्येक तत्व के लिए मापांक की जांच कर रहा है:

$ python -m timeit -s "lst = list(range(1000))" "lst1 = [x for x in lst if x % 10 == 0]"
1000 loops, best of 3: 525 usec per loop
$ python -m timeit -s "lst = list(range(1000))" "lst1 = lst[0::10]"
100000 loops, best of 3: 4.02 usec per loop

4
निश्चित रूप से, सूची बोध सामान्य से अधिक शक्तिशाली है। OTOH, प्रश्न एक मौजूदा सूची प्रस्तुत करता है और उस स्थिति में, एक स्लाइस ठीक काम करता है।
नेड डिली

मैंने सूची बोध उत्तरों में नीचे इस पर टिप्पणी की। "अगर x% 10 == 0" के साथ सावधान रहें। यह केवल इस विशेष सूची उदाहरण के साथ काम करता है, लेकिन यदि इनपुट सूची उदाहरण l = श्रेणी (0,1000,2) के लिए है, तो यह 10 वीं वस्तु से बाहर नहीं निकलेगी।
आंद्रे मिलर

12
@ और: बहुत सही है। तो यह एक विनम्र भाषा सुविधा का एक उदाहरण है, स्लाइस ऑपरेटर, जो इस मामले में निकलता है (1) सही परिणाम प्राप्त करना आसान बनाता है; (2) अधिक संक्षिप्त अभिव्यक्ति में परिणाम; और (3) तेजी से परिमाण के 2 आदेश होते हैं। (1) अब तक की सबसे महत्वपूर्ण चिंता है, लेकिन, भाषा के सावधानीपूर्वक डिजाइन और कार्यान्वयन के लिए, आपको 1. अच्छे प्रश्न और प्रतिक्रियाओं की कीमत के लिए तीनों मिलते हैं।
नेड डिली

2
0में अनावश्यक है l[0::10]l[::10]अधिक पठनीय है, कम भ्रामक है।
कोनस्टेंटिन शुबर्ट

Im सूची प्रदर्शन के लिए 0.5 सेकंड की तुलना और सूची स्लाइस के लिए 0.4 सेकंड से आश्चर्यचकित है। बहुत धीमी गति से लगता है, सूची स्लाइसिंग के लिए आकार 1 हजार की सूची के लिए 100 हजार छोरों की आवश्यकता क्यों है !?
दमो

57
  1. source_list[::10] सबसे स्पष्ट है, लेकिन यह किसी भी चलने के लिए काम नहीं करता है और बड़ी सूचियों के लिए स्मृति कुशल नहीं है।
  2. itertools.islice(source_sequence, 0, None, 10) किसी भी चलने योग्य के लिए काम करता है और स्मृति-कुशल है, लेकिन शायद बड़ी सूची और बड़े कदम के लिए सबसे तेज़ समाधान नहीं है।
  3. (source_list[i] for i in xrange(0, len(source_list), 10))

1
+1 सर्वश्रेष्ठ उत्तर, IMO। सभी तीनों एक सामान्य समाधान का प्रस्ताव देते हैं (यानी स्रोत सूची को दिए गए अनुसार लें)। जनरेटर समाधान (3.) अच्छा है क्योंकि यह स्रोत सूची के सूचकांक पर फिल्टर करता है। यह शायद 2 के रूप में स्मृति के रूप में कुशल है। दोनों सूचकांक और परिणाम सूची जनरेटर हैं और इस तरह से आलसी का निर्माण किया गया है, जो कि शायद सबसे तेज़ भी है यदि आपको एक सूची में परिणाम सूची की आवश्यकता नहीं है। केवल अगर स्रोत सूची एक जनरेटर हो सकती है तो मैं पॉल के "आइटम, मैं इन्युमरेट (एल)" मुहावरे के साथ जाऊंगा, क्योंकि जनरेटर की कोई लेन () नहीं है। BTW, किस प्रकार के चलने योग्य के साथ काम नहीं करेगा 1.? जेनरेटर ?!
थॉमस

Iterable = ऑब्जेक्ट __iter __ () मेथड रिटर्निंग इटरेटर (ऑब्जेक्ट विथ नेक्स्ट () मेथड)
डेनिस ओटकिड

24

आप इस तरह से स्लाइस ऑपरेटर का उपयोग कर सकते हैं:

l = [1,2,3,4,5]
l2 = l[::2] # get subsequent 2nd item

कैसे 3 से शुरू हर 2 आइटम प्राप्त करने के लिए?
14:

4
@ user1993L[2::2]
Nick Dandoulakis

19

मैनुअल से: s[i:j:k] slice of s from i to j with step k

li = range(100)
sub = li[0::10]

>>> sub
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]


4

केवल रेंज फ़ंक्शन के एक कदम पैरामीटर का उपयोग करने के लिए क्यों न करें :

l = range(0, 1000, 10)

तुलना के लिए, मेरी मशीन पर:

H:\>python -m timeit -s "l = range(1000)" "l1 = [x for x in l if x % 10 == 0]"
10000 loops, best of 3: 90.8 usec per loop
H:\>python -m timeit -s "l = range(1000)" "l1 = l[0::10]"
1000000 loops, best of 3: 0.861 usec per loop
H:\>python -m timeit -s "l = range(0, 1000, 10)"
100000000 loops, best of 3: 0.0172 usec per loop

3
@SilentGhost: यह सच है, लेकिन जैसा कि यह एक शुरुआती सवाल है कि रेंज फ़ंक्शन हो सकता है कि वे वास्तव में क्या करना चाहते हैं, इसलिए मुझे लगता है कि यह एक वैध उत्तर है। (हालांकि ऊपरी सीमा 1001 होनी चाहिए, 1000 नहीं)
स्कॉट ग्रिफ़िथ

2
existing_list = range(0, 1001)
filtered_list = [i for i in existing_list if i % 10 == 0]

1
यदि आपके पास श्रेणी (0, 1001, 10) है तो क्लॉज क्यों है जो पहले से ही प्रत्येक 10 वें तत्व को लेता है?
ऑटोप्लेक्टिक

4
एक ही टिप्पणी यहाँ, यह "सामान्य तरीके से बड़ी सूची में हर n'th आइटम की सूची वापस करने के लिए" सामान्य तरीके से हल नहीं करता है "आपका समाधान इस तथ्य पर निर्भर करता है कि उदाहरण सूची के मान 0 से 1000 हैं और केवल आइटम खींचते हैं प्रत्येक 10 वीं वस्तु के बजाय 10 से विभाज्य मान वाली सूची से बाहर।
आंद्रे मिलर

1
ठीक है, ओपी लिखता है: "हमारे पास शून्य से 1000 तक की संख्या की एक सूची है"। इसलिए उसे सामान्य समाधान की आवश्यकता नहीं है।

1
वह लिखता है 'कहो हमारे पास ..' इसका तात्पर्य सिर्फ एक उदाहरण से है। यदि वह वास्तव में हर 10 वें नंबर को शून्य से 1000 तक की सूची से बाहर करना चाहता था, तो इसका उत्तर रेंज (0,1001,10) या कुछ इसी तरह होगा।
आंद्रे मिलर

1

यहां "हर 10 वीं वस्तु" सूची समझ का बेहतर कार्यान्वयन है, जो सदस्यता परीक्षण के भाग के रूप में सूची सामग्री का उपयोग नहीं करता है:

>>> l = range(165)
>>> [ item for i,item in enumerate(l) if i%10==0 ]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160]
>>> l = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
>>> [ item for i,item in enumerate(l) if i%10==0 ]
['A', 'K', 'U']

लेकिन यह अभी भी सूची स्लाइसिंग का उपयोग करने की तुलना में बहुत धीमी है।


-9

सूची की समझ बिल्कुल उसी के लिए बनाई गई है:

smaller_list = [x for x in range(100001) if x % 10 == 0]

आप अजगर आधिकारिक दस्तावेज में उनके बारे में अधिक जानकारी प्राप्त कर सकते हैं: http://docs.python.org/tutorial/datastructures.html#list-comprehensions


ऊपरी बाउंड 1000 होना चाहिए, 10000 नहीं। आपके समाधान में लिस्ट-कॉम्प्रिहेंशन के लिंक के लिए 1000 से ऊपरी बाउंड को 999 पर बंद करना शामिल नहीं है। +1।

19
यह वास्तव में प्रत्येक 10 वीं वस्तु को बाहर नहीं निकालता है, यह 10. द्वारा विभाजित प्रत्येक आइटम को बाहर निकालता है, इस विशेष उदाहरण में इसकी एक ही बात है, लेकिन यह नहीं हो सकता है।
आंद्रे मिलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.