Rewrite the double loop better and possibly shorter

I am wondering if it is possible to write the following code a little better. Basically, I want to calculate z = f(x, y)for (x, y)meshgrid.

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])
+5
source share
7 answers

Yes. Your code presented in the question is good.

Never think a few lines are “good” or “cool”. What is considered clarity, readability and maintainability. Other people should understand your code (and you should understand it after 12 months when you need to find an error).

, , "" . . python. , .

+15

-

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

itertools ':

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

5 1, :

[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
+4

, ;

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

z, , , , .

: , lingrid, 100 , aaronasterling list assrehension; , .

+2

. 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. , numpy :

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.]])

np.ogrid linspace:

numpy np

>>> 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). , 1 , , , .


1 If your a, and bare numpy.array, then there will be a significant difference in performance because numpy arrays can handle much faster if there listnumpy.arrayrequired conversion.

0
source

All Articles