(Этот ответ касается простых оптимизаций и стиля Python; он работает с существующим алгоритмом, обучая некоторым точкам оптимизации, а не заменяя его более эффективным.)
Вот несколько моментов, чтобы сделать код более легким для чтения и понимания:
Итерация по списку sList, а не по диапазону (len (sList)). for i in range(len(sList))
становится for i in sList
, а sList[i]
становится i
.
Нет необходимости в этом tmpRad; вставьте это в строку.
Вместо if a: if b: if c:
используйте if a and b and c
.
Теперь мы находимся на этом:
filteredList = []
for i in sList:
minx = i['x'] - i['radius']
maxx = i['x'] + i['radius']
miny = i['y'] - i['radius']
maxy = i['y'] + i['radius']
minz = i['z'] - i['radius']
maxz = i['z'] + i['radius']
for j in nList:
if minx <= j['x'] <= maxx and miny <= j['y'] <= maxy and minz <= j['z'] <= maxz and findRadius(i,j) <= i['radius']:
filteredList.append(int(j['num']))
(PEP 8 рекомендует разбивать эту длинную строку на строки длиной не более 80 символов; PEP 8 также рекомендует filtered_list
и s_list
и n_list
вместо filteredList
, sList
и nList
.)
Я поставил findRadius(i, j) <= i['radius']
на первое место по стилю и потому, что, похоже, он с большей вероятностью оценит как ложное, ускоряя вычисления. Затем я также включил переменные minx
и т. Д.:
filteredList = []
for i in sList:
for j in nList:
if findRadius(i, j) <= i['radius'] \
and i['x'] - i['radius'] <= j['x'] <= i['x'] + i['radius'] \
and i['y'] - i['radius'] <= j['y'] <= i['y'] + i['radius'] \
and i['z'] - i['radius'] <= j['z'] <= i['z'] + i['radius']:
filteredList.append(int(j['num']))
Надо думать, что i['x'] - i['radius'] <= j['x'] <= i['x'] + i['radius']
можно упростить; попробуйте вычесть i['x']
из всех трех частей.
Вы можете сократить это еще больше с пониманием списка.
filteredList = [int(j['num']) for j in nList for i in sList
if findRadius(i, j) <= i['radius']
and i['x'] - i['radius'] <= j['x'] <= i['x'] + i['radius']
and i['y'] - i['radius'] <= j['y'] <= i['y'] + i['radius']
and i['z'] - i['radius'] <= j['z'] <= i['z'] + i['radius']]
И, наконец, именованных кортежей (у этого тоже есть побочный эффект - сделать их неизменяемыми, что, вероятно, желательно? Также обратите внимание, что это только Python 2.6, прочитайте страницу, чтобы узнать, как это можно сделать с помощью старые версии Python):
from collections import namedtuple
node = namedtuple('node', 'x y z num')
sphere = namedtuple('sphere', 'x y z radius')
nList = [
node(x=0.0, y=0.0, z=0.0, num=1.0),
node(x=1.0, y=0.0, z=0.0, num=2.0),
node(x=2.0, y=0.0, z=0.0, num=3.0),
node(x=3.0, y=0.0, z=0.0, num=4.0),
node(x=4.0, y=0.0, z=0.0, num=5.0),
node(x=5.0, y=0.0, z=0.0, num=6.0),
node(x=6.0, y=0.0, z=0.0, num=7.0),
node(x=7.0, y=0.0, z=0.0, num=8.0),
node(x=8.0, y=0.0, z=0.0, num=9.0),
node(x=9.0, y=0.0, z=0.0, num=10.0)]
sList = [
sphere(x=25.0, y=18.0, z=26.0, radius=0.0056470000000000001),
sphere(x=23.0, y=29.0, z=45.0, radius=0.0066280000000000002),
sphere(x=29.0, y=46.0, z=13.0, radius=0.014350999999999999),
sphere(x=20.0, y=0.0, z=25.0, radius=0.014866000000000001),
sphere(x=31.0, y=27.0, z=18.0, radius=0.018311999999999998),
sphere(x=36.0, y=10.0, z=46.0, radius=0.024702000000000002),
sphere(x=13.0, y=27.0, z=48.0, radius=0.027300999999999999),
sphere(x=1.0, y=14.0, z=13.0, radius=0.033889000000000002),
sphere(x=20.0, y=31.0, z=11.0, radius=0.034118999999999997),
sphere(x=28.0, y=23.0, z=8.0, radius=0.036683)]
Тогда вместо sphere['radius']
вы можете сделать sphere.radius
. Это делает код более аккуратным:
filteredList = [int(j.num) for j in nList for i in sList
if findRadius(i, j) <= i.radius
and i.x - i.radius <= j.x <= i.x + i.radius
and i.y - i.radius <= j.y <= i.y + i.radius
and i.z - i.radius <= j.z <= i.z + i.radius]
Или, без понимания списка,
filteredList = []
for i in sList:
for j in nList:
if findRadius(i, j) <= i.radius \
and i.x - i.radius <= j.x <= i.x + i.radius \
and i.y - i.radius <= j.y <= i.y + i.radius \
and i.z - i.radius <= j.z <= i.z + i.radius:
filteredList.append(int(j.num))
Наконец, выберите более подходящие имена; [стиль немного изменился в соответствии с комментариями, ставя findRadius
в конце, так как это с большей вероятностью будет вычислительно дорогостоящим - вы, однако, лучший судья в этом отношении]
filteredList = [int(n.num) for n in nodes for s in spheres
if s.x - s.radius <= n.x <= s.x + s.radius and
s.y - s.radius <= n.y <= s.y + s.radius and
s.z - s.radius <= n.z <= s.z + s.radius and
findRadius(s, n) <= s.radius]
Или,
filteredList = []
for s in spheres:
for n in nodes:
if (s.x - s.radius <= n.x <= s.x + s.radius and
s.y - s.radius <= n.y <= s.y + s.radius and
s.z - s.radius <= n.z <= s.z + s.radius and
findRadius(s, n) <= s.radius):
filteredList.append(int(n.num))
(Вы можете поместить srad = s.radius
во внешний цикл для возможного небольшого прироста производительности при желании.)