2013-04-28 108 views
0

我有一个坐标列表,我需要根据它们的x值将它们分成两半。事情是这样的:Python,分割坐标列表,基于x

l = [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (2, 1), (3, 1)] 
left = [] 
right = [] 
for i in l: 
    if i[0] < 2: 
     left.append(i) 
    else: 
     right.append(i) 

print(left) 
print(right) 

输出:

[(0, 0), (1, 0), (0, 1), (1, 1)] 
[(2, 0), (3, 0), (2, 1), (3, 1)] 

有一个更快的方法来做到这一点?

+1

你在一个循环中做,所以基本上我不认为有更快的方法。 – 2013-04-28 20:34:52

+2

相关:http://stackoverflow.com/q/949098/951890 – 2013-04-28 20:36:13

+1

你的代码在性能上是好的。 @LevLevitsky是对的,肯定可以写出更快的方法,但性能差异应该可以忽略不计。 – vaultah 2013-04-28 20:38:31

回答

1

这不是更快(2n),但也许更优雅,如果列表使用二分搜索进行排序,您可以得到的最好记录是n。

>>> l = [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (2, 1), (3, 1)] 
>>> left = [ x for x in l if x[0] < 2] 
>>> right = [ x for x in l if x[0] >= 2] 
5

你在O(n)中做。如果您已经对列表进行了排序,则可以在O(log(n))中执行此操作,方法是使用二分搜索搜索主元素。自己排序它只是为了使用二进制搜索不会得到回报,因为排序是O(n * log(n))

另一方面... 它真的很重要吗?如果这是你的瓶颈,那么可能重新考虑整个算法或数据结构。例如,如果您有一个复杂的问题,需要在某些区域的点上操作,则可以考虑使用kd-trees

0

如果您希望它更简洁一些,pythonic和可读的,而不会丢失O( n)的性能,这可能是其中一种方法 -

right = [] 
left = [coord for coord in l if (lambda t: True if t[0] < 2 else right.append(t) and False)(coord)] 

只在列表中迭代一次。

>>> l = [(0, 0), (1, 0), (2, 0), (3, 0), (0, 1), (1, 1), (2, 1), (3, 1)] 
>>> right = [] 
>>> left = [coord for coord in l if (lambda t: True if t[0] < 2 else right.append(t) and False)(coord)] 
>>> print '\n'.join([str(left), str(right)]) 
[(0, 0), (1, 0), (0, 1), (1, 1)] 
[(2, 0), (3, 0), (2, 1), (3, 1)] 
>>>