Issue
I'm trying to print out a dictionary (actually a defaultdict
) where the keys are version numbers (in the form 6.0
or 6.1.2
) and the values are floats.
# Parse file contents
firmware_percents = defaultdict(float)
with open('test.csv', 'r') as file:
reader = csv.DictReader(file)
for row in reader:
# Don't care about iphone vs ipad
# Must be a string - StrictVersion is apparently unhashable
rev = row["Firmware Version"].split(" ")[2]
# Dump extra spaces, the less than (assume .1%), and % sign
percent = float(row["% of Sessions"].strip().lstrip("<").strip("%"))
firmware_percents[rev] += percent
def pretty_print(d):
for k in sorted(d, key=d.get, reverse=True):
print("{0}: {1:.1f}".format(k, d[k]))
print("All versions:")
pretty_print(firmware_percents)
However, when I do this some versions are printing out of order:
All versions:
7.0: 44.2
7.0.2: 25.7
6.1.3: 14.2
6.1.4: 5.5
7.0.1: 3.2
6.1: 2.7
# You get the point
Using this input file:
Firmware Version,Sessions,% of Sessions
" iPhone 5.0.1 ",20," <0.1% "
" iPhone 6.0 ",26," 0.1% "
" iPhone 5.1.1 ",69," 0.3% "
" iPhone 5.1 ",2," <0.1% "
" iPhone 7.0 ",7401," 31.5% "
" iPhone 6.1 ",337," 1.4% "
" iPhone 6.1.3 ",2193," 9.3% "
" iPhone 6.1.2 ",84," 0.4% "
" iPhone 7.0.1 ",747," 3.2% "
" iPhone 7.0.2 ",4619," 19.7% "
" iPhone 6.0.1 ",37," 0.2% "
" iPhone 6.0.2 ",1," <0.1% "
" iPhone 6.1.4 ",1281," 5.5% "
" iPad 5.0 ",4," <0.1% "
" iPad 5.1 ",100," 0.4% "
" iPad 5.1.1 ",545," 2.3% "
" iPad 6.0 ",16," <0.1% "
" iPad 6.1 ",305," 1.3% "
" iPhone 7.0.3 ",1," <0.1% "
" iPhone 6.1.1 ",1," <0.1% "
" iPad 7.0 ",2979," 12.7% "
" iPad 6.0.1 ",100," 0.4% "
" iPad 6.1.3 ",1139," 4.9% "
" iPad 6.0.2 ",5," <0.1% "
" iPad 6.1.2 ",65," 0.3% "
" iPad 7.0.2 ",1404," 6.0% "
I've tried pprint
, and while it does sort in the correct order it doesn't format the floats (so I end up with numbers like 14.5999999996). It also occasionally prints strangeness like defaultdict(<class 'float'>, {'5': 3.3, '6': 24.2, '7': 73.2})
when I try to do major version only.
How can I ensure these print in version order with formatted percentages?
By order I mean it sorts by major then minor then build/super-minor (7.0.2 > 7.0.1 > 6.1.4 > 6.1 etc etc)?
Solution
I think @dornhege spotted the main issue first: key=d.get
means that you're sorting by the values, not the keys.
I'd leverage the stdlib package distutils
to get the version stuff handled automatically:
>>> sorted(firmware_percents, key=distutils.version.StrictVersion, reverse=True)
['7.0.3', '7.0.2', '7.0.1', '7.0', '6.1.4', '6.1.3', '6.1.2', '6.1.1', '6.1', '6.0.2', '6.0.1', '6.0', '5.1.1', '5.1', '5.0.1', '5.0']
>>> sorted(firmware_percents, key=distutils.version.LooseVersion, reverse=True)
['7.0.3', '7.0.2', '7.0.1', '7.0', '6.1.4', '6.1.3', '6.1.2', '6.1.1', '6.1', '6.0.2', '6.0.1', '6.0', '5.1.1', '5.1', '5.0.1', '5.0']
This has advantages over splitting by .
because it'll be smarter about handling things like 7.0.2rc1
.
Answered By - DSM
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.