def add_active_node(self, active_nodes, node): """Add a node to the active node list. The node is added so that the list of active nodes is always sorted by line number, and so that the set of (position, line, fitness_class) tuples has no repeated values. """
index = 0
# Find the first index at which the active node's line number # is equal to or greater than the line for 'node'. This gives # us the insertion point. while (index < len(active_nodes) and active_nodes[index].line < node.line): index = index + 1
insert_index = index
# Check if there's a node with the same line number and # position and fitness. This lets us ensure that the list of # active nodes always has unique (line, position, fitness) # values. while (index < len(active_nodes) and active_nodes[index].line == node.line): if (active_nodes[index].fitness_class == node.fitness_class and active_nodes[index].position == node.position): # A match, so just return without adding the node return
index = index + 1
active_nodes.insert(insert_index, node)
I determined that len was being called a large number of times so did a first rewrite as (minus comments)
def add_active_node(self, active_nodes, node): index = 0 nan = len(active_nodes) node_line = node.line node_fitness_class = node.fitness_class node_position = node.position
while index < nan and active_nodes[index].line<node_line: index += 1
insert_index = index
while index<nan and active_nodes[index].line==node_line: if (active_nodes[index].fitness_class==node_fitness_class and active_nodes[index].position==node_position): return
index += 1
active_nodes.insert(insert_index, node)
which gives a good speedup even so I decided to eliminate the index += 1 in the first while loop which results in
def add_active_node(self, active_nodes, node): nan = len(active_nodes) node_line = node.line node_fitness_class = node.fitness_class node_position = node.position
insert_index = nan for index, a in enumerate(active_nodes): if a.line>=node_line: insert_index = index break index = insert_index
while index<nan and active_nodes[index].line==node_line: if (active_nodes[index].fitness_class==node_fitness_class and active_nodes[index].position==node_position): return
index += 1
active_nodes.insert(insert_index, node)
and this change also results in a significant speedup and is I believe is still equivalent. I'm not sure exactly why this is faster than the while loop, but it is.
However, it seems harder to get the same speedup for the last while loop; that loop is probably not such a problem so it's not terribly important.
Is there a fast way to get enumerate to operate over a slice of an iterable? -- Robin Becker
-- http://mail.python.org/mailman/listinfo/python-list