эффективный алгоритм редактирования списка

У меня есть облако 3D-точек, сохраненное в двух списках. Пример с 5 точками (x, y, z): (3,3,3), (1,1,1), (4,4,4), (2,2,2), (5,5,5 ) -> Мои списки выглядят так:

z = [3, 1, 4, 2, 5] # the z values pts = [(3,3), (1,1), (4,4), (2,2), (5,5)] # the x and y values 

Теперь я хочу исключить все значения, где значение z больше 3:

 # what I want to receive: z = [3, 1, 2] pts = [(3,3), (1,1), (2,2)] 

Мой алгоритм здесь:

 k = -1 for i in range(len(z)): k += 1 if z[k] > h: z.pop(k) pts.pop(k) k -= 1 

Это возвращает меня именно то, что я хочу – но это очень медленно (для> 100 000 значений). Я подумал о том, чтобы сначала отсортировать свой список через z.sort() а затем сделать z = z [: index] – но когда я это сделаю для своего z-списка, тогда мой список pts все еще не отсортирован. И даже если бы я мог сортировать оба списка, мне также не нужно проходить длинный loop чтобы найти индекс, где мое условие true ? Кто-нибудь знает более эффективное решение?

 z, pts = zip(*[(z, pt) for z, pt in zip(z, pts) if z <= 3]) print z, pts 

Вывод

 (3, 1, 2) ((3, 3), (1, 1), (2, 2)) 

С itertools:

 from itertools import izip, ifilter 

молчать вместе

 zipped_coords = izip(z, pts) 

фильтр (в сообщении вы указываете higher , но результаты с вытеснением на самом деле ниже, сначала выбираются)

 filtered_coords = ifilter(lambda x: x[0]>=3, zipped_coords ) 

расстегнуть молнию

 znew, ptsnew = map(list, izip(*filtered_coords)) 

или все-в-одном oneliner

 >>> znew, ptsnew = map(list, izip(*ifilter(lambda x: x[0]>=3, izip(z, pts)))) >>> print znew, ptsnew [3, 4, 5] [(3, 3), (4, 4), (5, 5)] 

Поскольку вы удаляете элементы из списка при повторении, это алгоритм O (N ^ 2). Вы можете использовать простое понимание списка вместе с zip чтобы сделать это в линейном времени.

 z = [3, 1, 4, 2, 5] # the z values pts = [(3,3), (1,1), (4,4), (2,2), (5,5)] # the x and y values merged = zip(z, pts) filtered = [x for x in merged if x[0] <= 3] z, pts = zip(*filtered)