0

defaultdictキーがバージョン番号 (6.0またはの形式6.1.2) で、値が floatである辞書 (実際には ) を出力しようとしています。

# 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)

ただし、これを行うと、一部のバージョンが順不同で印刷されます。

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

この入力ファイルの使用:

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% "

を試してみましpprintたが、正しい順序でソートされますが、フロートはフォーマットされません (したがって、14.5999999996 のような数値になります)。また、defaultdict(<class 'float'>, {'5': 3.3, '6': 24.2, '7': 73.2})メジャーバージョンのみを実行しようとすると、奇妙に出力されることがあります。

これらがフォーマットされたパーセンテージでバージョン順に印刷されるようにするにはどうすればよいですか?

順番は、メジャー、マイナー、ビルド/スーパーマイナー (7.0.2 > 7.0.1 > 6.1.4 > 6.1 など) でソートされることを意味しますか?

4

3 に答える 3

5

@dornhege が最初に主な問題を発見したと思いkey=d.getます。つまり、キーではなく値でソートしていることを意味します。

stdlib パッケージdistutilsを利用して、バージョンのものを自動的に処理します。

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

などの処理がよりスマートになるため、分割するよりも利点が.あります7.0.2rc1

于 2013-09-30T15:45:09.143 に答える
2

ソートのためにバージョン番号を整数のリストに変換します。

def pretty_print(d):
    for k in sorted(d, key=lambda x: x.split("."), reverse=True):
        print("{0}: {1:.1f}".format(k, d[k]))

ただし、を使用するoperator.methodcallerと、おそらくもう少し効率的です。

from operator import methodcaller
def pretty_print(d):
    for k in sorted(d, key=methodcaller('split', '.'), reverse=True):
        print("{0}: {1:.1f}".format(k, d[k]))
于 2013-09-30T15:35:19.593 に答える
1

Pythonでは、辞書はソート可能ではありません.辞書の「get」メソッドをソートキーとして使用するレシピは、キーではなく辞書の値でソートされます。

したがって、呼び出すとfor k in sorted(d, key=d.get, reverse=True) 、辞書内の各キーが辞書の「get」メソッドに渡され、代わりに値が取得されます。

キーでソートしたい場合は、「キー」に値を渡す必要はまったくありません。ただ行う: for k in sorted(d, reverse=True):

ただし、文字列比較であるため、「10.1」などのバージョンは「2.0」よりも先に表示されます。バージョン番号を「.」で分割し、各部分を数値に変換すると、代わりに正しい比較が行われます。

for k in sorted(d, key=lambda x: tuple(int(n) for n in x.split(".")) , reverse=True):

于 2013-09-30T15:35:03.637 に答える