在python中运行循环有限的迭代

时间:2011-10-18 08:38:04

标签: python for-loop

我有一个非常大的对象列表,我需要找到所有具有相同属性的对象(any_object.any_attribute),然后将它们附加到新列表中。所以我已经预先对它们进行了排序并运行了二元搜索算法。 我找到了具有匹配属性的对象,但问题是有多个这样的对象(它们是邻居)但我无法弄清楚在这些连续对象上运行循环的干净方法,以便它们都可以追加。我的代码粘贴在下面。

  low   = 0
  high  = len(sortedObjects)
  while low < high:
    mid = (low + high)/2
    if sortedObjects[mid].attr < desired_attr:
      low = mid + 1
    elif sortedSamples[mid].attr > desired_attr:
      high = mid
    else:
      newList.append(sortedObjects[mid])
      break

所以我需要在最后一个else块中编写一些新代码,这些代码将迭代具有相同属性的所有对象并附加它们。听起来像是一个for循环但是有可能在有限的迭代中运行for循环,就像在C中一样吗?

我不想迭代整个列表,因为这会慢一点,而且这个脚本的要求之一就是它必须快速有效。它将在非常大的数据集上运行,我们正在寻找10-12小时的执行时间。提前谢谢!

3 个答案:

答案 0 :(得分:4)

试试这个:

else:
    # Find the first element that matches
    while mid > 0 and sortedSamples[mid - 1].attr == desired_attr:
        mid -= 1

    # Iterate until an element that doesn't match is found.
    while mid < len(sortedSamples) and sortedSamples[mid].attr == desired_attr:
        newList.append(sortedObjects[mid])
        mid += 1

这在O(m)时间内运行,其中m是具有所需属性的对象数。

答案 1 :(得分:2)

如果您要更频繁地执行此搜索,请创建此属性的列表:

attr_list = [o.attr for o in sortedObjects]

然后使用bisect模块:

import bisect
left_i = bisect.bisect_left(attr_list, desired_attr)
right_i = bisect.bisect_right(attr_list, desired_attr, left_i)
newList = sortedObjects[left_i:right_i]

答案 2 :(得分:0)

在else块中运行第二个循环,在此处减少mid,直到找到第一个对象,然后循环前进以获取所有对象。您可以通过保存旧mid来加快速度,并在“向后循环”中找到它们时保存元素,然后在前向循环之前再次向前跳转。