2015-11-20 3 views
2

Я хотел бы создать список, содержащий начальную точку x = [x0 x1] и возмущенную точку y1 = [x0+h x1], y2 = [x0-h x1], y3 = [x0 x1+h] и т.д. Я попытался это:Update некоторые элементы в списке

xs = [x]*5; 
for i in range(len(x)): 
    if isinstance(h, float): 
     xs[2*i+1][i] -= h; 
     xs[2*i+2][i] += h; 

Но это, кажется, изменить элементы взад и вперед по мере прохождения цикла.

+3

'[х] * 5' составляет список, где все элементы являются ссылками на тот же список. измените это на '[x [:] для i в диапазоне (5)]', чтобы создать копию каждого списка. –

+0

. Ваш вопрос для меня не имеет смысла. Вы начинаете с того, что говорите, что у вас есть список с одним элементом, я думаю («[x0 x1]» означает «[(x0, x1)]??), Тогда ваш предлагаемый код пытается ссылаться на вложенный список? –

+0

Вам нужна функция для точек в плоскости (т. Е. С двумя координатами), как предлагает ваше объяснение; или точек с произвольным числом координат, как кажется, кажется вашим «примерным» кодом (который имеет много ошибок)? – LeartS

ответ

2

Если я правильно интерпретировать то, что вы хотели сделать из вашего объяснения и код:

def perturbate(x, h): 
    """ 
    Given an initial point x = [x0, x1, ..., xn] 
    Returns a list of points containing the original point and, 
    for every coordinate, "perturbations" of that point created 
    by adding and subtracting 'h' to the coordinate. 
    """ 
    # start with the original point plus 
    # 2 copies of it for every coordinate 
    points = [x[:] for i in range(len(x)*2 + 1)] 

    for coordinate_index in range(len(x)): 
     points[coordinate_index*2 + 1][coordinate_index] -= h 
     points[coordinate_index*2 + 2][coordinate_index] += h 
    return points 

Что дает:

>>> perturbate([1.0,2.0], 1.0) 
[[1.0, 2.0], [0.0, 2.0], [2.0, 2.0], [1.0, 1.0], [1.0, 3.0]] 

Так в основном ваш код был почти правильно (но не совсем понятно, , переменные с общим именем не помогают), за исключением инициализации «результатов»: когда вы делаете [x] * 5, где x - изменяемый объект, вы создаете список из 5 раз того же объекта , Если вы измените свойство этого объекта, оно изменится во всех индексах, потому что они ссылаются на один и тот же объект!

>>> a = [[0,0]] * 5 
>>> a 
[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] 
>>> a[0][0] = 1 
>>> a 
[[1, 0], [1, 0], [1, 0], [1, 0], [1, 0]] 
>>> 

Кроме того, предполагается, жестко 5 2-мерных точек. Но если мы предполагаем 2-мерные точки, то почему использовать len точки вместо того, чтобы просто использовать более простую и понятную «жестко запрограммированную» реализацию?

+0

Я привел простой пример более общего кода, поэтому у меня был len (x), но это могло быть только 2, вы правы. И спасибо за быстрый ответ, это было очень полезно! – Gregory

2

Я утверждаю, что принятый ответ на этот вопрос излишне усложнен, что затрудняет рассуждение и поэтому сложнее отлаживать и поддерживать. Он также более сложный, поскольку он излишне заполняет список, который затем ему нужно перебирать.

несколько менее сложное общее решение, как выше будет выглядеть следующим образом:

def perturbate(x, h): 
    perturbations = [x] # initialize with original point first 
    for i, _ in enumerate(x): # no range(len()) 
     shifted_down = x[:] 
     shifted_down[i] -= h 
     perturbations.append(shifted_down) 
     shifted_up = x[:] 
     shifted_up[i] += h 
     perturbations.append(shifted_up) 
    return perturbations 

Кроме того, это общее решение с поддержкой до п-мерных точек гораздо менее читабельным, чем просто написание его, если вам «вновь работает в 2D:

def perturbate(point, h): 
    x, y = point 
    return [[x, y], [x-h, y], [x+h, y], [x, y-h], [x, y+h]] 

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

Помните:

+0

Во-первых, мой код был основан на его коде, так как я хотел показать, где ошибка была в его коде. А также потому, что вопрос был не так понятен перед редактированием и дополнительными комментариями, поэтому нужно было угадать, что он хотел сделать из своего кода. Во-вторых, «мое» (фактически его) решение не O (N^2), это O (n). В-третьих, мы все можем согласиться с тем, что для 2D-точек жесткое кодирование является гораздо более читаемым и простым, чем общее решение, как я сказал себе в своем ответе. – LeartS

+0

Вы говорите, что код OP - O (N^2), что неверно. Вы говорите, что не используете 'xrange (len)', но тогда вы используете «перечисление», которое учитывает только индекс (https://stackoverflow.com/questions/11901081/only-index-needed-enumerate-or-xrange). И, что самое главное, ** вы не рассматриваете проблему OP, то есть единственное, что объективно неправильно в его коде **. Вместо этого вы ответили в основном обзором кода. Мой ответ также был опущен, и все же он объяснил (с примерами) ошибку в коде OP, предоставил рабочий код (на основе кода OP), и он предоставил ваши же полезные указатели за 1 день до этого. Идите фигуру. – LeartS

+0

Принятые ответы предпочитают перечислять по общим причинам, которые здесь не применимы, верхний ответ по числу upvotes предпочитает xrange, потому что более явный. Что касается сложности, если вы считаете, что копируете точку O (N), то оба алгоритма O (N^2). Ваш алгоритм также выполняет 'x [:]' внутри цикла! Фактически, я тестировал как с 10 100 000 000 10000 координат, так и с теми же (очень плохо!) В любом случае, вы правы, ваш ответ, в то время как я все еще чувствую, что он действительно не «неявно показывает ошибку», не заслуживают понижения. Если вы его отредактируете, я могу изменить голосование. – LeartS

Смежные вопросы