Python 3.1- Grid Simulation Conceptual issue

老子叫甜甜 提交于 2019-12-06 14:37:45

First off, I'm not quite sure what you're asking, so forgive me if I've completely misunderstood your question...

You say that you only want to modify the first item that equals a given value, and not all of them. If so, you're going to need to add a break after you find the first value, otherwise you'll continue looping and modify all the other values.

However, there are better ways to do what you want.

Also, you're importing numpy at top and then never(?) using it...

This is exactly the sort of thing that you'd want to use numpy for, so I'm going to give an example of using it.

It appears that you're just applying a function to a 3x3 moving window of a 2D array, where the values of the array match some given value.

If we want to set 3x3 area around a given index to some value, we'd just do something like this:

x[i-1:i+1, j-1:j+1] = value 

...where x is your array, i and j are the row and column, and value is the value you want to set them to. (similarly, x[i-1:i+1, j-1:j+1] returns the 3x3 array around <i,j>)

Furthermore, if we want to know the <i,j> indicates where a particular value occurs within an array, we can use numpy.argwhere which will return a list of the <i,j> indicates for each place where a given condition is true.

(Using conditionals on a numpy array results in a boolean array showing where the condition is true or false. So, x >= 10 will yield a boolean array of the same shape as x, not simply True or False. This lets you do nice things like x[x>100] = 10 to set all values in x that are above 100 to 10.)

To sum it all up, I believe this snippet does what you want to do:

import numpy as np

# First let's generate some data and set a few duplicate values
data = np.arange(100).reshape(10,10)
data[9,9] = 2
data[8,6] = 53

print 'Original Data:'
print data

# We want to replace the _first_ occurences of "samples" with the corresponding
# value in "grid_details" within a 3x3 window...
samples = [2, 53, 69]
grid_details = [200,500,100]

nrows, ncols = data.shape
for value, new_value in zip(samples, grid_details):
    # Notice that were're indexing the _first_ item than argwhere returns!
    i,j = np.argwhere(data == value)[0]

    # We need to make sure that we don't index outside the boundaries of the
    # array (which would cause a "wraparound" assignment)
    istart, istop = max(i-1, 0), min(i+2, nrows)
    jstart, jstop = max(j-1, 0), min(j+2, ncols)

    # Set the value within a 3x3 window to be "new_value"
    data[istart:istop, jstart:jstop] = new_value

print 'Modified Data:'
print data

This yields:

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

Modified Data:
[[  0 200 200 200   4   5   6   7   8   9]
 [ 10 200 200 200  14  15  16  17  18  19]
 [ 20  21  22  23  24  25  26  27  28  29]
 [ 30  31  32  33  34  35  36  37  38  39]
 [ 40  41 500 500 500  45  46  47  48  49]
 [ 50  51 500 500 500  55  56  57 100 100]
 [ 60  61 500 500 500  65  66  67 100 100]
 [ 70  71  72  73  74  75  76  77 100 100]
 [ 80  81  82  83  84  85  50  87  88  89]
 [ 90  91  92  93  94  95  96  97  98   2]]

Finally, you mentioned that you wanted to "view something as both an N-dimensional array and a "flat" list". This is in a sense what numpy arrays already are.

For example:

import numpy as np

x = np.arange(9)
y = x.reshape(3,3)

print x
print y

y[2,2] = 10000

print x
print y

Here, y is a "view" into x. If we change an element of y we change the corresponding element of x and vice versa.

Similarly, if we have a 2D array (or 3D, 4D, etc) that we want to view as a "flat" 1D array, you can just call flat_array = y.ravel() where y is your 2D array.

Hope that helps, at any rate!

You didn't specify that you had to do it any specific way so I'm assuming you're open to suggestions. A completely different(and IMHO simpler) way would be to make an array of arrays:

grid = [[0,0,0,0,0],
        [0,0,0,2,0],
        [1,0,0,0,0],
        [0,0,0,0,0],
        [0,0,3,0,0]]

To access a location on the grid, simply supply the index of the list(the row), then the index of the location on that grid(the column). For example:

1 = grid[2][0]
2 = grid[1][3]
3 = grid[4][2]

To create a non-hardcoded grid(e.g. of a variable size):

def gridder(width,height):
    list = []
    sublist = []
    for i in range(0,width):
        sublist.append(1)
    for i in range(0,height):
        list.append(sublist)
    return list

To modify a part of your grid:

def modifier(x,y,value):
    grid[y][x] = value

*If this is homework and you're supposed to do it the way the specified in your answer, then you probably can't use this answer.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!