2010-12-17 9 views
5

मुझे आश्चर्य है कि निम्न कोड कुछ हद तक अच्छी तरह से लिखा जा सकता है या नहीं। असल में, मैं (x, y) मेष्रिड के लिए z = f(x, y) की गणना करना चाहता हूं।एक अच्छे और शायद छोटे रास्ते में एक डबल लूप को फिर से लिखें

a = linspace(0, xr, 100)                 
b = linspace(0, yr, 100)                 

for i in xrange(100): 
    for j in xrange(100): 
     z[i][j] = f(a[i],b[j]) 

उत्तर

15

हाँ। प्रश्न में प्रस्तुत आपका कोड अच्छा है।

कभी भी यह न सोचें कि कुछ पंक्तियां "अच्छी" या "शांत" हैं। स्पष्टता, पठनीयता और रखरखाव क्या मायने रखता है। अन्य लोगों को आपके कोड को समझने में सक्षम होना चाहिए (और आपको इसे 12 महीने में समझना चाहिए, जब आपको एक बग खोजने की आवश्यकता होती है)।

कई प्रोग्रामर, विशेष रूप से युवा, चीजें जो "चालाक" समाधान वांछनीय हैं। वो नहीं हैं। और यह पाइथन समुदाय के साथ इतना अच्छा है। हम दूसरों की तुलना में उस गलती से बहुत कम पीड़ित हैं।

+1

मैंने इसे ऊपर उठाया क्योंकि यह एक सबक है कि मैं खुद को सीख रहा हूं लेकिन अगर वे सिर्फ सूचियां हैं तो मुझे लगता है कि मेरा समाधान ओपी के कोड से बेहतर है क्योंकि यह अपरिवर्तनीय इटरेटर को हटा देता है। एक ही धारणा के साथ, गेहूं का जवाब अभी तक बेहतर है। – aaronasterling

+1

इटेटर अभी भी वहां हैं। यह कुछ भी नहीं छोड़ता है। उस ने कहा कि मैं हर समय सूची समझ का उपयोग करता हूं, लेकिन अगर मुझे उन्हें घोंसला करना है तो मैं उन्हें विस्तारित करता हूं, इसलिए उन्हें पढ़ने में आसान लगता है। –

5

क्या आप यह सब एक ही बार में सेट करते हैं

z = [[f(item_a, item_b) for item_b in b] for item_a in a] 
2

की तरह कुछ कर सकता है, आप एक सूची समझ का उपयोग कर सकते हैं;

[[f(a[i], b[j]) for j in range(100)] for i in range(100)] 

आप एक z पहले से ही वहाँ है कि का उपयोग करने की जरूरत है, हालांकि, आप ऐसा नहीं कर सकते और अपने कोड में neatest आप मिल जाएगा के बारे में है।

अलावा: मैं क्या इस lingrid करता है के साथ पता नहीं है, लेकिन अगर यह एक 100 तत्व सूची पैदा करता है, aaronasterling की सूची समझ का उपयोग करें; यदि आपको आवश्यकता नहीं है तो अतिरिक्त इटरेटर बनाने में कोई बात नहीं है।

4

आप itertools 'उत्पाद इस्तेमाल कर सकते हैं:

[f(i,j) for i,j in product(a, b)] 

और यदि आप वास्तव में तो 1 में उन 5 लाइनों हटना चाहते हैं:

[f(i,j) for i,j in product(linspace(0,xr,100), linspace(0,yr,100)] 

इसे आगे भी लेने के लिए यदि आप के एक समारोह चाहते हैं xr और yr जहां आप 0 और 100 की श्रेणियों को किसी अन्य चीज़ पर भी प्रीसेट कर सकते हैं:

def ranged_linspace(_start, _end, _function): 
    def output_z(xr, yr): 
     return [_function(i, j) for i,j in product(linspace(_start, xr, _end), linspace(_start, yr, _end))] 
    return output_z 
+0

यह ध्यान दिया जाना चाहिए कि इन सभी समाधानों में ओपी के समाधान जैसे नेस्टेड सूची की बजाय एक-आयामी सूची उत्पन्न होती है। – aaronasterling

0

यह सामान्य परिणाम दिखाता है। a एक सूची में बनाया गया है 6-लंबा और b 4-लंबा है। नतीजा 6 सूचियों की एक सूची है, और प्रत्येक नेस्टेड सूची 4 तत्व लंबी है।

>>> def f(x,y): 
...  return x+y 
... 
>>> a, b = list(range(0, 12, 2)), list(range(0, 12, 3)) 
>>> print len(a), len(b) 
6 4 
>>> result = [[f(aa, bb) for bb in b] for aa in a] 
>>> print result 
[[0, 3, 6, 9], [2, 5, 8, 11], [4, 7, 10, 13], [6, 9, 12, 15], [8, 11, 14, 17], [10, 13, 16, 19]] 
0

मुझे लगता है कि यह एक लाइन कोड है कि आप के लिए

z = [[a+b for b in linspace(0,yr,100)] for a in linspace(0,xr,100)] 
0

आपका linspace देख है वास्तव में है जैसे कि यह np.linspace हो सकता है लग रहा है।

z = f(x[:, np.newaxis], y) 

उदाहरण के लिए::

>>> import numpy as np 
>>> x = np.linspace(0, 9, 10) 
>>> y = np.linspace(0, 90, 10) 
>>> x[:, np.newaxis] + y # or f(x[:, np.newaxis], y) 
array([[ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90.], 
     [ 1., 11., 21., 31., 41., 51., 61., 71., 81., 91.], 
     [ 2., 12., 22., 32., 42., 52., 62., 72., 82., 92.], 
     [ 3., 13., 23., 33., 43., 53., 63., 73., 83., 93.], 
     [ 4., 14., 24., 34., 44., 54., 64., 74., 84., 94.], 
     [ 5., 15., 25., 35., 45., 55., 65., 75., 85., 95.], 
     [ 6., 16., 26., 36., 46., 56., 66., 76., 86., 96.], 
     [ 7., 17., 27., 37., 47., 57., 67., 77., 87., 97.], 
     [ 8., 18., 28., 38., 48., 58., 68., 78., 88., 98.], 
     [ 9., 19., 29., 39., 49., 59., 69., 79., 89., 99.]]) 

लेकिन आप भी दो linspace के बजाय np.ogrid इस्तेमाल कर सकते हैं:

आयात numpy यदि यह आप स्पष्ट रूप से पुनरावृति बिना NumPy सरणी पर काम कर सकता है एनपी

>>> x, y = np.ogrid[0:10, 0:100:10] 
>>> x + y # or f(x, y) 
array([[ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90], 
     [ 1, 11, 21, 31, 41, 51, 61, 71, 81, 91], 
     [ 2, 12, 22, 32, 42, 52, 62, 72, 82, 92], 
     [ 3, 13, 23, 33, 43, 53, 63, 73, 83, 93], 
     [ 4, 14, 24, 34, 44, 54, 64, 74, 84, 94], 
     [ 5, 15, 25, 35, 45, 55, 65, 75, 85, 95], 
     [ 6, 16, 26, 36, 46, 56, 66, 76, 86, 96], 
     [ 7, 17, 27, 37, 47, 57, 67, 77, 87, 97], 
     [ 8, 18, 28, 38, 48, 58, 68, 78, 88, 98], 
     [ 9, 19, 29, 39, 49, 59, 69, 79, 89, 99]]) 

यह कुछ हद तक निर्भर करता है आप f पर हैं। यदि इसमें math.sin जैसे फ़ंक्शन शामिल हैं तो आपको उन्हें numpy.sin द्वारा प्रतिस्थापित करने की आवश्यकता है।

तो इसके बारे में numpy तो नहीं है या तो आप अपने विकल्प के साथ या जब पाशन वैकल्पिक enumerate का उपयोग कर रहना चाहिए:

for idx1, ai in enumerate(a): 
    for idx2, bj in enumerate(b): 
     z[idx1][idx2] = f(ai, bj) 

यह लाभ है कि आप को हार्डकोड करने के लिए अपने range (या xrange) या आवश्यकता नहीं है इनपुट के रूप में len(a) का उपयोग करें। लेकिन सामान्य रूप से यदि कोई बड़ा प्रदर्शन अंतर नहीं है तब आपके कोड का उपयोग करके आप और अन्य विधि का उपयोग आसानी से समझ जाएगा। >numpy.array रूपांतरण के लिए आवश्यक हैं -


अपने a और b तो numpy.array रों हैं तो क्योंकि NumPy सरणी के बहुत तेजी से संसाधित कर सकते हैं अगर कोई list < वहाँ एक महत्वपूर्ण प्रदर्शन अंतर हो जाएगा।

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