2011-02-02 81 views
1

目標是將一維數組視爲2D網格。第二個1D數組給出了需要在網格中更改的值列表,第三個數組指示了多少。Python 3.1-網格模擬概念問題

問題在於圍繞修改後的值的值也會發生變化。

下面的示例保留爲一維數組,但對其進行計算,就好像它是2D網格一樣。有用;但目前它會更改網格中與1D列表(樣本)中的值相匹配的所有值。我不想只將1值及其周圍值轉換爲列表中的1值。

即,如果列表是[2,3];我只想改變迭代中出現的第一個2和3值。目前的例子是,每2個網格改變一次。

什麼讓我感到困惑的是(可能是因爲我已經構建了修改計算的方式),我不能簡單地遍歷網格並在每次匹配時刪除列表值。

預先感謝您的時間!

代碼如下;

import numpy 

def grid_range(value): 
    if value > 60000: 
     value = 60000 
     return (value) 
    elif value < 100: 
     value = 100 
     return(value) 
    elif value <= 60000 and value >= 100: 
     return(value) 


def grid(array,samples,details): 

    original_length = len(array) 
    c = int((original_length)**0.5) 

    new_array = []                 #create a new array with the modified values 

    for elem in range (len(array)):             #if the value is in samples 
     if array[elem] in samples: 
      value = array[elem] + (array[elem] * (details[1]/100)) 
      test_range = grid_range(value) 
      new_array.append(test_range) 

     elif ((elem + 1) < original_length) and array[elem - 1] in samples:           #change the one before the value         
      if (len(new_array) % c == 0) and array[elem + 1] not in samples:        
       new_array.append(array[elem]) 
      else: 
       new_forward_element = array[elem] +(array[elem] * (details[2]/100)) 
       test_range1 = grid_range(new_forward_element) 
       new_array.append(test_range1) 

     elif ((elem + 1) < original_length) and (array[elem + 1]) in samples:  #change the one before and that it doesn't attempt to modify passed the end of the array         
      if (len(new_array) + 1) % c == 0: 
       new_array.append(array[elem]) 
      else: 
       new_back_element = array[elem] +(array[elem] * (details[2]/100)) 
       test_range2 = grid_range(new_back_element)  
       new_array.append(test_range2) 

     elif ((elem+c) <= (original_length - c))and(array[elem + c]) in samples: #if based on the 9 numbers on the right of the keyboard with test value numebr 5; this is position '2' 
      extra1 = array[elem] +(array[elem] * (details[2]/100)) 
      test_range3 = grid_range(extra1) 
      new_array.append(test_range3) 

     elif (array[abs(elem - c)]) in samples:          #position '8' 
      extra2 = array[elem] +(array[elem] * (details[2]/100)) 
      test_range4 = grid_range(extra2) 
      new_array.append(test_range4) 

     elif (array[abs(elem - (c-1))]) in samples:         #position '7' 
      if (elem - (c-1)) % c == 0: 
       new_array.append(array[elem]) 
      else: 
       extra3 = array[elem] +(array[elem] * (details[2]/100)) 
       test_range5 = grid_range(extra3) 
       new_array.append(test_range5) 

     elif (array[abs(elem - (c+1))]) in samples:         #position '9'  
      if (elem - (c+1) + 1) % c == 0: 
       new_array.append(array[elem]) 

      else: 
       extra4 = array[elem] +(array[elem] * (details[2]/100)) 
       test_range6 = grid_range(extra4) 
       new_array.append(test_range6) 

     elif ((elem +(c-1)) < original_length) and (array[elem + (c-1)]) in samples: #position '1', also not passed total array length 
      if (elem + (c-1)+ 1) % c == 0: 
       new_array.append(array[elem]) 
      else:    
       extra5 = array[elem] +(array[elem] * (details[2]/100)) 
       test_range7 = grid_range(extra5) 
       new_array.append(test_range7) 

     elif (elem + (c+1)) < (len(array)- c) and (array[elem + (c+1)]) in samples:  #position '3', also not passed total array length 
      if (elem + (c+1)) % c == 0: 
       new_array.append(array[elem]) 
      else: 
       extra6 = array[elem] +(array[elem] * (details[2]/100)) 
       test_range8 = grid_range(extra6) 
       new_array.append(test_range8) 

     else: 
      new_array.append(array[elem]) 

    return(new_array) 


a = [16,2,20,4,14,6,70,8,9,100,32,15,7,14,50,20,17,10,9,20,7,17,50,2,19,20] 
samples = [2] 
grid_details = [10,50,100] 

result = grid(a,samples,grid_details) 

編輯:

根據您的回答喬,我創建了修改主值(中心),通過特定%,而其他周邊元件的一個版本。但是,如何確保在下次樣本迭代過程中更改的值不會再次被轉換。

謝謝你的時間!

示例代碼:

def grid(array,samples,details): 

    #Sides of the square (will be using a squarable number 
    Width = (len(array)) ** 0.5 
    #Convert to grid 
    Converted = array.reshape(Width,Width) 
    #Conversion details 
    Change = [details[1]] + [details[2]] 
    nrows, ncols = Converted.shape 

    for value in samples: 

     #First instance where indexing returns it 
     i,j = np.argwhere(Converted == value)[0] 

     #Prevent indexing outside the boudaries 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 their "new_value" 
     for elem in Converted[istart:istop, jstart:jstop]: 

     Converted[elem] = elem + (elem * (value * ((Change[1]/100)) 

     #Set the main value to the new value 
     Converted[i,j] = value + (value * ((Change[0])/100)) 


    #Convert back to 1D list 
    Converted.tolist() 

    return (Converted) 


a = [16,2,20,4,14,6,70,8,9,100,32,15,7,14,50,20,17,10,9,20,7,17,50,2,19,20,21,22,23,24,25] 
samples = [2, 7] 
grid_details = [10,50,100] 

result = grid(a,samples,grid_details) 

print(result) 

PS:我wan't避免修改在網格中,先前已被修改的任何值,假如是主值或周圍的值。

回答

2

首先,我不太清楚你在問什麼,所以請原諒我,如果我完全誤解了你的問題......

你說你只想修改等於給定值的第一項,而不是全部。如果是這樣,在找到第一個值後,您將需要添加break,否則您將繼續循環並修改所有其他值。

但是,有更好的方法來做你想做的。

而且,你要導入numpy的在頂部,然後永遠不會(?),用它...

這正是那種你想使用numpy的對的事情,所以我打算給出一個使用它的例子。

看來您只是將函數應用於2D數組的3x3移動窗口,其中數組的值與某個給定值匹配。

如果我們想圍繞着一個給定的指標爲某個值3x3的領域,我們只希望做這樣的事:

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

...其中x是你的陣列,ij都行和列,value是您想要設置的值。 (同樣,x[i-1:i+1, j-1:j+1]返回各地<i,j> 3×3陣列)

此外,如果我們想知道<i,j>表示在該特定值出現在陣列中,我們可以使用numpy.argwhere將返回<i,j>列表表示每個地方一個給定的條件是真的。

(在numpy的陣列產生一個布爾陣列示出的條件是真還是假使用條件語句。所以,x >= 10將產生相同的形狀的一個布爾陣列x簡單地TrueFalse。這使你做的好東西像x[x>100] = 10設置在x是高於100〜10)

所有值總結這一切,我相信這個片段做了你想做的事:

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 

這產生了:

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

最後,你提到你想「某種看法既是一個N維數組和一個‘平面’清單」。這在某種意義上已經是numpy數組了。

例如:

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 

這裏,y是一個 「視圖」 到x。如果我們改變y的元素,我們改變相應的元素x,反之亦然。同樣,如果我們有一個2D陣列(或3D,4D等),我們希望將其視爲一個「扁平」1D陣列,則可以調用flat_array = y.ravel(),其中y是您的二維數組。

無論如何希望有所幫助!

2

您沒有指定您必須以任何特定方式進行操作,因此我假設您已接受建議。 一個完全不同的(和IMHO簡單)的方法是使數組的數組:

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

要在網格上訪問的位置,只需提供列表(行)的索引,則該索引該網格上的位置(該列)。例如:

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

要創建一個非硬編碼的網格(例如可變大小的):

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 

要修改網格的一部分:

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

*如果這是家庭作業,你應該按照你的答案中指定的方式來做,那麼你可能無法使用這個答案。

+0

幫助我的理解,謝謝你的評論和時間! – jimy 2011-02-02 14:17:26

+0

@jimy:如果有幫助,請注意。 – John 2011-02-02 16:21:48