क्या सीमा (len (a)) की आवश्यकता है?


85

एक अक्सर एसओ पर अजगर प्रश्नों में इस प्रकार के भाव पाता है। या तो बस चलने योग्य के सभी मदों तक पहुँचने के लिए

for i in range(len(a)):
    print(a[i])

जो लिखने का एक बोझिल तरीका है:

for e in a:
    print(e)

या चलने के तत्वों को निर्दिष्ट करने के लिए:

for i in range(len(a)):
    a[i] = a[i] * 2

जो समान होना चाहिए:

for i, e in enumerate(a):
     a[i] = e * 2
# Or if it isn't too expensive to create a new iterable
a = [e * 2 for e in a]

या सूचकांकों को छानने के लिए:

for i in range(len(a)):
    if i % 2 == 1: continue
    print(a[i])

जिसे इस तरह व्यक्त किया जा सकता है:

for e in a [::2]:
    print(e)

या जब आपको केवल सूची की लंबाई की आवश्यकता होती है, और इसकी सामग्री की नहीं:

for _ in range(len(a)):
    doSomethingUnrelatedToA()

जो हो सकता है:

for _ in a:
    doSomethingUnrelatedToA()

अजगर हमारे पास में enumerate, टुकड़ा करने की क्रिया, filter, sorted, आदि ... के रूप में अजगर forनिर्माणों पुनरावृति को iterables से अधिक करना है और न केवल पूर्णांकों का पर्वतमाला, वहाँ वास्तविक दुनिया उपयोग-मामलों में जहां आप की जरूरत है in range(len(a))?


5
मुझे लगता range(len(a))है कि आमतौर पर ऐसे लोग हैं जो पाइथन के साथ काफी अनुभवहीन हैं (हालांकि सामान्य रूप से प्रोग्रामिंग के साथ जरूरी नहीं है)।
rlms

मैंने केवल तभी उपयोग किया range(len(a))जब मैं अजगर सीख रहा था। आजकल, मैं नहीं करता, क्योंकि जैसा कि आपने बताया, इसे बदलना काफी आसान है।

ज़रुरी नहीं। मैं range(len(a))अक्सर उपयोग करता हूं , क्योंकि मुझे सूची की सामग्री की आवश्यकता नहीं है, लेकिन केवल लंबाई।
एकिड

8
क्या होगा यदि लूप में मुझे वर्तमान एक से पहले और बाद में तत्व तक पहुंचने की आवश्यकता है? मैं आमतौर पर है कि for i in range(len(a)): doSomethingAbout(a[i+1] - a[i])कैसे चारों ओर पाने के लिए?
झांग

1
@ JaakkoSeppälä सहमत हुए। मैं सिर्फ उदाहरणों के माध्यम से लूप होने के मुख्य मुद्दे को स्पष्ट करने के लिए एक उदाहरण दे रहा था, न कि केवल मूल्यों को समझने के लिए, अंत में एक कोने का मामला है जो मुख्य बिंदु के अलावा है।
झांग

जवाबों:


17

यदि आपको किसी अनुक्रम के सूचकांक के साथ काम करने की आवश्यकता है, तो हाँ - आप इसका उपयोग करते हैं ... उदाहरण के लिए numpy.argsort के बराबर : ...

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]

ठीक है, यह समझदार लग रहा है। आपका बहुत बहुत धन्यवाद। लेकिन सवाल यह है: आप सूचकांकों की अपनी नई छंटनी सूची के साथ क्या करेंगे। यदि इस सूची के माध्यम से फिर से आप कुछ पुनरावृत्तियों का उपयोग करते हैं, तो कुत्ता अपनी पूंछ काटता है।
हाइपरबोरस

1
समतुल्य: [ix for ix, _ in sorted(enumerate(a), key=lambda i: i[1])]हालांकि, हालांकि तुम्हारा यकीनन अच्छा है / geekier।
एरिक कप्लून

10

यदि आपको सूची के दो तत्वों को एक साथ एक्सेस करने की आवश्यकता हो तो क्या होगा?

for i in range(len(a[0:-1])):
    something_new[i] = a[i] * a[i+1]

आप इसका उपयोग कर सकते हैं, लेकिन यह शायद कम स्पष्ट है:

for i, _ in enumerate(a[0:-1]):
     something_new[i] = a[i] * a[i+1]

व्यक्तिगत रूप से मैं 100% खुश नहीं हूँ!


1
for ix, i in enumerate(a)समतुल्य लगता है, नहीं?
एरिक कपलुन

2
इसके बजाय जोड़ीदार का उपयोग करना चाहिए ।
उड़ान भेड़

उन स्थितियों में मैं करता हूं:for a1,a2 in zip(a[:-1],a[1:])
लुका अमेरियो

7

संक्षिप्त उत्तर : गणितीय रूप से बोलना, नहीं, व्यावहारिक रूप से, हां, उदाहरण के लिए Intentional Programming।

तकनीकी रूप से, उत्तर "नहीं, इसकी आवश्यकता नहीं है" क्योंकि यह अन्य निर्माणों का उपयोग करने में स्पष्ट है। लेकिन व्यवहार में, मैं यह स्पष्ट करने के लिए उपयोग करता हूं for i in range(len(a)(या for _ in range(len(a))अगर मुझे सूचकांक की आवश्यकता नहीं है) कि मैं कई बार इसे क्रमबद्ध करना चाहता हूं क्योंकि किसी भी चीज के लिए अनुक्रम में वस्तुओं का उपयोग करने की आवश्यकता के बिना एक क्रम में आइटम हैं।

तो: "क्या कोई ज़रूरत है?" ? - हाँ, मुझे इसकी आवश्यकता है कि पठनीय उद्देश्यों के लिए कोड के अर्थ / आशय को व्यक्त करूँ ।

इसे भी देखें: https://en.wikipedia.org/wiki/Intentional_programming

और जाहिर है, अगर कोई संग्रह नहीं है जो कि पुनरावृत्ति के साथ जुड़ा हुआ for ... in range(len(N))है, एकमात्र विकल्प है, इसलिए इसका सहारा नहीं लेना चाहिएi = 0; while i < N; i += 1 ...


क्या फायदे for _ in range(len(a))हुए for _ in a?
हाइपरबोरस

@ हाइपरबोरस: हाँ, मैंने आपकी टिप्पणी से कुछ सेकंड पहले ही अपने उत्तर में संशोधन कर दिया था ... इसलिए मुझे लगता है कि अंतर यह है कि क्या आप वास्तव में "कई बार दोहराए जाने वाले सामानों केa बारे में स्पष्ट होना चाहते हैं " जैसे कि "हरaa चीज के विपरीत " हैं। तत्व में , " की सामग्री की परवाह किए बिना ... ... तो बस एक जानबूझकर प्रोग्रामिंग की बारीकियों।
एरिक कप्लून

आपके उदाहरण के लिए धन्यवाद। मैंने इसे अपने प्रश्न में शामिल किया है।
हाइपरबोरस

2
एक सूची के प्राप्त करने के लिए 'hello'सूची में के रूप में कई वस्तुओं के रूप में के साथ a, का उपयोग करेंb = ['hello'] * len(a)
steabert

2

टिप्पणियों के साथ ही व्यक्तिगत अनुभव से जा रहे हैं, मुझे कोई कहते हैं, कोई नहीं है की जरूरत के लिए range(len(a))। आप जो कुछ भी कर सकते हैं range(len(a))वह दूसरे (आमतौर पर कहीं अधिक कुशल) तरीके से किया जा सकता है।

आपने अपनी पोस्ट में कई उदाहरण दिए हैं, इसलिए मैं उन्हें यहां नहीं दोहराऊंगा। इसके बजाय, मैं उन लोगों के लिए एक उदाहरण दूंगा जो कहते हैं "क्या होगा अगर मुझे सिर्फ लंबाई aचाहिए, आइटम नहीं?"। यह केवल एक बार आप उपयोग करने पर विचार कर सकते हैं range(len(a))। हालांकि, यहां तक ​​कि ऐसा किया जा सकता है:

>>> a = [1, 2, 3, 4]
>>> for _ in a:
...     print True
...
True
True
True
True
>>>

क्लेमेंट्स का उत्तर (जैसा कि अल्लिक द्वारा दिखाया गया है) को हटाने के लिए भी काम किया जा सकता है range(len(a)):

>>> a = [6, 3, 1, 2, 5, 4]
>>> sorted(range(len(a)), key=a.__getitem__)
[2, 3, 1, 5, 4, 0]
>>> # Note however that, in this case, range(len(a)) is more efficient.
>>> [x for x, _ in sorted(enumerate(a), key=lambda i: i[1])]
[2, 3, 1, 5, 4, 0]
>>>

तो, निष्कर्ष में, जरूरतrange(len(a)) नहीं है । इसका केवल उल्टा पठनीयता है (इसका आशय स्पष्ट है)। लेकिन यह सिर्फ वरीयता और कोड शैली है।


आपका बहुत बहुत धन्यवाद। और फिर फिर, देखने वाले की नज़र में पठनीयता (आंशिक रूप से) है। मैं for _ in a:"Iterate से अधिक लेकिन इसकी सामग्री को अनदेखा करता हूं for _ in range(len(a))" के रूप में व्याख्या करता हूं, लेकिन मैं इसके रूप में व्याख्या करता हूं "की लंबाई प्राप्त करें, फिर उसी लंबाई के कई पूर्णांक बनाएं, और फिर अंत में सामग्री को अनदेखा करें"।
हाइपरबोरस

1
@ हाइपरबोरस - बहुत सही। यह सिर्फ कोड शैली है। मेरा लक्ष्य यह दिखाना था कि कभी भी "मुझे उपयोग range(len(a))नहीं करना चाहिए या मैं ऐसा नहीं कर सकता"

एक तरफ ध्यान दें: एग में एकल अंडरस्कोर गुमनाम चर है। यह एकमात्र चर है जिसे अन्य चर के विपरीत फिर से सौंपा जा सकता है (या "मिलान किया गया"), जैसा कि erlang विनाशकारी असाइनमेंट की अनुमति नहीं देता है (जो आम तौर पर बोलना एक घृणा है और हमारे और नितंबों के बीच घूंघट को कमजोर करता है, जहां HE अपने महल में दीवार के पीछे इंतजार करता है जो यातनाग्रस्त कांच से बना है)।
हाइपरबोरस

2

कभी-कभी matplotlib की आवश्यकता होती है range(len(y)), जैसे, जबकि y=array([1,2,5,6]), plot(y)ठीक काम करता है, scatter(y)नहीं। एक को लिखना है scatter(range(len(y)),y)। (व्यक्तिगत रूप से, मुझे लगता है कि यह एक बग है scatter, plotऔर इसके दोस्तों scatterऔर stemयथासंभव कॉलिंग दृश्यों का उपयोग करना चाहिए)


2

जब आपको किसी तरह के हेरफेर के लिए सूचकांक का उपयोग करने की आवश्यकता होती है और वर्तमान तत्व पर्याप्त नहीं होता है, तो यह अच्छा है। उदाहरण के लिए, एक बाइनरी ट्री लें, जो एक सरणी में संग्रहीत है। यदि आपके पास एक ऐसी विधि है जो आपको ट्यूपल्स की एक सूची वापस करने के लिए कहती है जिसमें प्रत्येक नोड सीधे बच्चे होते हैं तो आपको सूचकांक की आवश्यकता होती है।

#0 -> 1,2 : 1 -> 3,4 : 2 -> 5,6 : 3 -> 7,8 ...
nodes = [0,1,2,3,4,5,6,7,8,9,10]
children = []
for i in range(len(nodes)):
  leftNode = None
  rightNode = None
  if i*2 + 1 < len(nodes):
    leftNode = nodes[i*2 + 1]
  if i*2 + 2 < len(nodes):
    rightNode = nodes[i*2 + 2]
  children.append((leftNode,rightNode))
return children

बेशक, यदि आप जिस तत्व पर काम कर रहे हैं वह एक वस्तु है, तो आप बस एक बच्चों को प्राप्त करने की विधि कह सकते हैं। लेकिन हाँ, आपको वास्तव में केवल सूचकांक की आवश्यकता है यदि आप किसी प्रकार का हेरफेर कर रहे हैं।


1

मेरे पास एक उपयोग का मामला है, मुझे विश्वास नहीं है कि आपका कोई उदाहरण कवर है।

boxes = [b1, b2, b3]
items = [i1, i2, i3, i4, i5]
for j in range(len(boxes)):
    boxes[j].putitemin(items[j])

मैं अजगर के लिए अपेक्षाकृत नया हूं, हालांकि अधिक सुरुचिपूर्ण दृष्टिकोण जानने के लिए बहुत खुश हूं।


4
मेरी अज्ञानता जिप है, समानांतर में 2 सूचियों पर पुनरावृत्ति करने का एक बहुत अधिक पायथोनिक तरीका है।
जिम

1
हाह, मैं वास्तव में इसी तरह के उपयोग के मामले के साथ आया था ... [a - b for a, b in zip(list1, list2)]बहुत अच्छा है की तुलना में [list1[i] - list2[i] for i in range(len(list1))].. धन्यवाद!
केवलर

1

यदि आपको len(a)किसी वस्तु के पहले आइटम पर पुनरावृति करना है b(जो इससे बड़ा है a), तो आपको संभवतः उपयोग करना चाहिए range(len(a)):

for i in range(len(a)):
    do_something_with(b[i])

2
यह स्पष्ट हो सकता है:for b_elem in b[:len(a)]:...
जलीय कछुए

@aquirdturtle शायद यह स्पष्ट है, लेकिन आपका समाधान एक नई सूची बनाता है, जो कि महंगा हो सकता है यदि b & a बड़े हैं।
PM 2Ring

इसके itertools.isliceबजाय इसका उपयोग करना चाहिए ।
मिस्टरमियागी

1

कभी-कभी, आप वास्तव में संग्रह के बारे में परवाह नहीं करते हैं । उदाहरण के लिए, कच्चे डेटा के साथ "सन्निकटन" की तुलना करने के लिए एक सरल मॉडल फिट लाइन बनाना:

fib_raw = [1, 1, 2, 3, 5, 8, 13, 21] # Fibonacci numbers

phi = (1 + sqrt(5)) / 2
phi2 = (1 - sqrt(5)) / 2

def fib_approx(n): return (phi**n - phi2**n) / sqrt(5)

x = range(len(data))
y = [fib_approx(n) for n in x]

# Now plot to compare fib_raw and y
# Compare error, etc

इस मामले में, फाइबोनैचि अनुक्रम के मूल्य स्वयं अप्रासंगिक थे। यहां हमें जो कुछ भी चाहिए था वह उस इनपुट अनुक्रम का आकार था जिसकी हम तुलना कर रहे थे।


मैं पायथन के लिए नया हूं, इस मामले में ** क्या करते हैं? मैंने * args और ** kwargs के बारे में पढ़ा है, लेकिन यह अलग दिखता है।
lukas_o

1
घातांक। n की शक्ति को phi।
मतीन उल्हाक

0

बहुत सरल उदाहरण:

def loadById(self, id):
    if id in range(len(self.itemList)):
        self.load(self.itemList[id])

मैं एक ऐसे समाधान के बारे में नहीं सोच सकता जो रेंज-लेन की रचना का जल्दी से उपयोग न करे।

लेकिन शायद इसके बजाय यह try .. exceptpythonic रहने के साथ किया जाना चाहिए मुझे लगता है ..


1
if id < len(self.itemList) लेकिन try...exceptबेहतर है, जैसा आप कहते हैं।
saulspatz

यह आईडी <0.
IARI

0

मेरा कोड है:

s=["9"]*int(input())
for I in range(len(s)):
    while not set(s[I])<=set('01'):s[i]=input(i)
print(bin(sum([int(x,2)for x in s]))[2:])

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

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