Python 3.1- Grid Simulation Концептуальная проблема - PullRequest
1 голос
/ 02 февраля 2011

Цель состоит в том, чтобы рассматривать одномерный массив как двумерную сетку. Второй 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)

EDIT:

Основываясь на вашем ответе Джо, я создал версию, которая изменяет основное значение (центр) на определенный%, а окружающие элементы - на другой. Тем не менее, как я могу гарантировать, что измененные значения не будут преобразованы снова во время следующей итерации образцов.

Спасибо за ваше время!

Пример кода:

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: Я не хочу избегать изменения любого значения в сетке, которое было ранее изменено, будь то основное значение или окружающие значения.

Ответы [ 2 ]

2 голосов
/ 02 февраля 2011

Прежде всего, я не совсем уверен, что вы спрашиваете, так что простите, если я полностью неправильно понял ваш вопрос ...

Вы говорите, что хотите изменить только первый элемент, которыйравно заданному значению, а не всем им.Если это так, вам нужно будет добавить break после того, как вы найдете первое значение, в противном случае вы продолжите цикл и измените все другие значения.

Однако есть более эффективные способы сделать то, чтовы хотите.

Кроме того, вы импортируете numpy сверху, а затем никогда (?) не используете его ...

Это именно то, что вы хотели бы использовать numpyдля, поэтому я собираюсь привести пример его использования.

Похоже, что вы просто применяете функцию к движущемуся окну 3х3 2D-массива, где значения массива соответствуют некоторым заданнымзначение.

Если мы хотим установить область 3x3 вокруг заданного индекса на некоторое значение, мы просто сделаем что-то вроде этого:

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

... где x - ваш массив,i и j - это строка и столбец, а value - это значение, которое вы хотите установить.(аналогично, x[i-1:i+1, j-1:j+1] возвращает массив 3x3 около <i,j>)

Более того, если мы хотим знать, <i,j> указывает, где конкретное значение встречается в массиве, мы можем использовать numpy.argwhere, который вернет список <i,j>, указывающих для каждого места, где данное условие истинно.

(Использование условных обозначений в массиве numpy приводит к булевому массиву, показывающему, где условие истинно или ложно. Таким образом, x >= 10 приведет к логическому массиву той же формы, что и x, not просто True или False. Это позволяет вам делать такие приятные вещи, как 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-мерный массиви «плоский» список ».Это в некотором смысле, какие массивы уже есть.

Например:

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 - это ваш 2D-массив,

Надеюсь, это поможет, во всяком случае!

2 голосов
/ 02 февраля 2011

Вы не указали, что должны были сделать это каким-то определенным образом, поэтому я предполагаю, что вы открыты для предложений.Совершенно другим (и 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

* Если это домашнее задание, и вы должны делать это так, как указано в вашем ответе, то вы, вероятно, не сможете использовать этот ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...