1 2 3 4 5 6 7 8 9 10 11 12 13
def get_pos(rel_dates): """returns the positions of the dates closest to 25%, 50%, and 75%""" pos = [0] # first element dates25, dates50, dates75 = [], [], [] for date in rel_dates: dates25.append(abs(date-25)) dates50.append(abs(date-50)) dates75.append(abs(date-75)) pos.append(dates25.index(min(dates25))) pos.append(dates50.index(min(dates50))) pos.append(dates75.index(min(dates75))) pos.append(len(rel_dates)-1) #last element return pos
Refactorings
No refactoring yet !
Kevin Baribeau
January 30, 2010, January 30, 2010 20:39, permalink
You may or may not like this.
Instead of building pos with append, I build the whole thing in one line. I also used list comprehensions to build the dates.
I think both changes are more declarative, but probably less newbie friendly.
1 2 3 4 5 6 7 8 9 10 11 12 13
def get_pos(rel_dates): """returns the positions of the dates closest to 25%, 50%, and 75%""" dates25 = [abs(date-25) for date in rel_dates] dates50 = [abs(date-50) for date in rel_dates] dates75 = [abs(date-75) for date in rel_dates] return [ 0, dates25.index(min(dates25)), dates50.index(min(dates50)), dates75.index(min(dates75)), len(rel_dates)-1 ]
Ants
January 31, 2010, January 31, 2010 07:01, permalink
It looks a bit frightening that both implementations above use O(3 * N) space for the 3 new arrays created, and at best O(3 * N) complexity to determine the minimum value from each of those new arrays.
bob
February 14, 2010, February 14, 2010 18:58, permalink
Since the array is sorted, you should use binary search. Look at the "bisect" module and the bisect.bisect() family of functions.
onk
March 7, 2010, March 07, 2010 21:07, permalink
@bob's bisect.
1 2 3 4 5 6 7 8 9 10 11 12 13
from bisect import bisect def pos(ls, x): pos = bisect(ls, x) if ls[pos] - x > x - ls[pos - 1]: return pos - 1 else: return pos def spots(rel_dates): """Returns the positions of the dates closest to 25%, 50%, and 75%""" return [pos(rel_dates, x) for x in [25, 50, 75]]
Colin Wallace
April 13, 2010, April 13, 2010 22:43, permalink
I simply re-wrote redundant parts of the code. It's shorter, and more memory-efficient, but probably not any faster.
1 2 3 4 5 6 7 8
def get_pos(rel_dates): """returns the positions of the dates closest to 25%, 50%, and 75%""" ret = [0] for sub in xrange(25, 100, 25): dates = [abs(date-sub) for date in rel_dates] ret.append(dates.index(min(dates))) ret.append(len(rel_dates)-1) return ret
The function takes an list of floats ranging from 0.0 to 100.0 in an ascending order. It returns a list of indexes with the indexes of the elements closest to 25.0, 50.0 and 75.0.
The intention is to label a time axis, where the labels should correspond to their relative position.