693a4661eaa71435ce5ebe61de64c5a4

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.

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 !

F571a96564c78a854662a00358c33160

Kevin Baribeau

January 30, 2010, January 30, 2010 20:39, permalink

No rating. Login to rate!

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.

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
		]
F9a9ba6663645458aa8630157ed5e71e

Ants

January 31, 2010, January 31, 2010 07:01, permalink

No rating. Login to rate!

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.

D41d8cd98f00b204e9800998ecf8427e

bob

February 14, 2010, February 14, 2010 18:58, permalink

No rating. Login to rate!

Since the array is sorted, you should use binary search. Look at the "bisect" module and the bisect.bisect() family of functions.

3ac88630891949b4e0fa568f413d8cdb

onk

March 7, 2010, March 07, 2010 21:07, permalink

No rating. Login to rate!

@bob's bisect.

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]]
Dc77b8da112bc303c377785538c6228f

Colin Wallace

April 13, 2010, April 13, 2010 22:43, permalink

No rating. Login to rate!

I simply re-wrote redundant parts of the code. It's shorter, and more memory-efficient, but probably not any faster.

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

Your refactoring





Format Copy from initial code

or Cancel