I have the understanding that Python is all about efficiency. How would I write the code below to be more Pythonic?
I thought of using a dictionary, but since the conditions for the elif
statement are ranges, I don't think that's possible.
threshold_scale
if pop in range(threshold_scale[0], threshold_scale[1]):
color = '#ff0000'
elif pop in range(threshold_scale[1], threshold_scale[2]):
color = '#f6ff00'
elif pop in range(threshold_scale[2], threshold_scale[3]):
color = '#00ff08'
elif pop in range(threshold_scale[3], threshold_scale[4]):
color = '#0d00ff'
elif pop in range(threshold_scale[4], threshold_scale[5]+1):
color = '#ff00f7'
Output
[1960, 648065, 1294170, 1940275, 2586380, 3232486]
An interval tree is designed for these types of queries. One example is the intervaltree
module.
from intervaltree import IntervalTree, Interval
threshold_scale = [1960, 648065, 1294170, 1940275, 2586380, 3232486]
ranges = zip(threshold_scale, threshold_scale[1:])
colors = ["#ff0000", "#f6ff00", "$00ff08", "$0d00ff", "$ff00f7"]
t = IntervalTree([Interval(x, y, c) for (x,y), c in zip(ranges, colors)])
pop = 2000
color = sorted(t[2000])[0].data
For n
intervals, it takes O(n lg n)
to build the interval tree, and a single query takes O(lg n)
time. (Technically, it's O(lg n + m)
, where m
is the number of items in the result. Our tree consists of non-overlapping ranges, though, so m
always equals 1.)
By comparison, your if
statement would take O(n)
time. Each pop in range(...)
takes O(1)
time, but there could be O(n)
of them. Using an interval tree is faster if you need to make many queries against the same set of intervals.
colors = [
'#ff0000',
'#f6ff00',
'#00ff08',
'#0d00ff',
'#ff00f7',
]
color = next(c for c, t_range in
zip(colors, zip(threshold_scale, threshold_scale[1:])) if
pop in range(*t_range))
Given input:
threshold_scale = [0,2,4,6,8,10]
pop = 7
Outputs:
f6ff00
You can use numpy.digitize
import numpy as np
threshold_scale = [1960, 648065, 1294170, 1940275, 2586380, 3232486]
pop = [2000, 2000000, 2800000]
color = np.array(['#ff0000', '#f6ff00', '#00ff08', '#0d00ff', '#ff00f7'])
color[np.digitize(pop, threshold_scale) - 1]
You will have to deal with pop values outside of covered range too...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.