Ускорение работы скрипта, избегая ненужных повторных вычислений во вложенном цикле for-for-if - PullRequest
0 голосов
/ 21 января 2020

Предположим, есть ~ 10 ** 2 круга известных позиций и радиусов. Также предположим, что есть ~ 10 ** 3 точки известных позиций. Распределение является абсолютно случайным, мы знаем, что если мы исследуем каждый круг, в принципе, он может иметь более 1 точки.

Следующий фрагмент кода python предназначен для l oop сначала над кружками, а затем над точками. Как написано, для каждого круга внутренняя l oop будет повторно вычислять посторонние линии, если нужно только отслеживать круги, которые имеют хотя бы 1 точку.

Например, если в одном круге 100 точек, самый внутренний l oop будет выполнен 100 раз. Но мне нужно избегать этого, манипулируя кодом так, чтобы, когда одна точка находилась внутри круга, l oop перестала проверять этот круг для остальных точек. Таким образом, я бы значительно увеличил скорость своего кода. Тем не менее, я не совсем уверен, как сделать трюк.

# position_data and radius_data are the properties of the circles mentioned above
for circle_position, circle_radius in zip(position_data, radius_data): 

    #(x, y) are the coordinates of the points mentioned above
    for x, y in zip(vals1, vals2):   

        if (condition1 and condition2 and condition3):
            # do some stuff  (these are the stuff that I want to avoid due to repetition)

1 Ответ

3 голосов
/ 21 января 2020

Вы смотрели на заявление на перерыв? См. Python разбить и продолжить .

. В вашем условном выражении проверьте, была ли найдена точка внутри окружности, и разбейте, если истина, код ниже:

# position_data and radius_data are the properties of the circles mentioned above
for circle_position, circle_radius in zip(position_data, radius_data): 

    #(x, y) are the coordinates of the points mentioned above
    for x, y in zip(vals1, vals2):   

        # Condition to check if a point was found within a circle
        if point_in_circle(circle_position, circle_radius, x, y):
            break

Для этого условного утверждения я бы порекомендовал вытащить проверку point_in_circle в отдельную функцию для удобства чтения и повторного использования:

def point_in_circle(cx, cy, cr, px, py):
    d = math.sqrt(
        (px - cx) ** 2 + (py - cy) ** 2
    )

    if d < cr:
        return True

Здесь cx, cy и cr - это позиция x круга, позиция y и радиус

px, py - это точки x и y.


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

# NEW
pointsWithinCircles = 0
totalPoints = len(vals1)

def point_in_circle(position_data, radius_data, x, y):
    in_circle = False
    # Logic

    return in_circle

for circle_position, circle_radius in zip(position_data, radius_data):

    for x, y in zip(vals1, vals2):

        if point_in_circle(circle_position, circle_radius, x, y):

            # NEW - Increment counter
            pointsWithinCircles += 1
            break

#NEW
pointsOutsideCircles = totalPoints - pointsWithinCircles

Вы можете создать счетчик, чтобы отслеживать, сколько точек содержится в кругах. Затем вычтите pointsWithinCircles из общего количества набранных вами баллов, которое просто равно длине вашего списка vals1 (или vals2).

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