LoginSignup
11
9

More than 5 years have passed since last update.

複雑な構造を持つ辞書のValueソート(深いところのValueでkey構造ごとソート)

Last updated at Posted at 2016-09-09

Complex Value Sortとでも呼んでおく(これ何ソート?)

  • 指定する辞書のvalueが構造を持つケース
  • 複雑な辞書のvalueの中のどこかの値でkey以下の構造をソートする。
  • key以下の構造を維持する形でソートする。
  • 指定の値が文字列か数値かには注意する。(""やNoneは、事前に弾くか0にでもしておく)

例えば、こんな辞書構造があって

Adic = {
                                   ↓こことか              ↓ここを軸にソートしたい
            'C134':{"price":30,"sales":"1000","profit":200 ,"alist":[110,20,30 ,50]}, 
            'C623':{"price":80,"sales":"100" ,"profit":6   ,"alist":[100,10,30 ,50]},
            'C430':{"price":70,"sales":"5000","profit":1000,"alist":[160,11,120,6]},
            'C115':{"price":10,"sales":"2400","profit":40  ,"alist":[80 , 1,10 ,6]}
        }

ポイントはラムダ式の返り値の表現

sorted()でValue構造内のソートしたい値を指定する(この場合x[1]が内側の辞書型になる)。
 key = lambda x: x[1]['profit']

指定したい値がより深い所にある場合たどる必要がある
(x[1]['alist']がリストに相当、その2番目を指定)
 key = lambda x: x[1]['alist'][1]

基本はコレ

dic = {'A':10000, 'B':2010, 'C':5, 'D':500}
res = sorted(dic.items(), key=lambda x: x[1]) #value指定
res = sorted(pathD.items(), key=lambda x: int(x[0])) #ちなみにkeyがstrの時のkeyでソート指定

ラムダは関数の略と思えば読める。

def lambda(x): return 2x --> lambda x:2x

dict型は、xに(key,value)タプルが飛び込んでくるので0番か1番か指定している。

import collections
from prettyprint import pp, pp_str #ppはお好みのでどうぞ最近は公式のがあったはず
from collections import OrderedDict

Adic = {
            #この4列をvalue内のどこかのvalue値でソートする
            'C134':{"price":30,"sales":"1000","profit":200 ,"alist":[110,20,30,50]}, 
            'C623':{"price":80,"sales":"100" ,"profit":6   ,"alist":[100,10,30,50]},
            'C430':{"price":70,"sales":"5000","profit":1000,"alist":[160,11,120,6]},
            'C115':{"price":10,"sales":"2400","profit":40  ,"alist":[80,1,10,6]}
        }

# xには辞書から出てきたタプルが入ってくる感じ。タプルの中をたどってValue指定
# Listで返るので注意
# 全部降順指定:reverse=True
pp('profitでソート')
res1 = sorted(Adic.items(), key=lambda x: x[1]['profit'],reverse=True)
pp(res1)

pp('salesでソート(文字列はintに変換)')
res2 = sorted(Adic.items(), key=lambda x: int(x[1]['sales']),reverse=True)
pp(res2)

pp('alistの2個めでソート')
res3 = sorted(Adic.items(), key=lambda x: x[1]['alist'][1],reverse=True)
pp(res3)

pp('key sort(バックから3つで数字を抜く。3ケタとか固定の場合)')
res4 = sorted(Adic.items(), key=lambda x: int (x[0][-3]) ,reverse=True)#int なくても一応どうにかなる
pp(res4)

pp('key sort(先頭の文字"C"をカット)')
res5 = sorted(Adic.items(), key=lambda x: int(x[0].lstrip('C')) ,reverse=True)
pp(res5)

pp('profitでソート2')
res6 = OrderedDict(sorted(Adic.items(), key=lambda x: x[1]['profit'],reverse=True))
print(res6)#ppだと中で順序がくずれる。
pp(type(res6))

結果 

profitのケースだけとりあえず貼ります。
profitの値、1000, 200, 40, 6で降順に構造ごとソートできている!
key的には、c430, c134, c115, c623の構造順になっている。
OrderedDictは、古テクのppと相性が悪い。

"profitでソート"
[
    [
        "C430", 
        {
            "alist": [
                160, 
                11, 
                120, 
                6
            ], 
            "price": 70, 
            "profit": 1000, 
            "sales": "5000"
        }
    ], 
    [
        "C134", 
        {
            "alist": [
                110, 
                20, 
                30, 
                50
            ], 
            "price": 30, 
            "profit": 200, 
            "sales": "1000"
        }
    ], 
    [
        "C115", 
        {
            "alist": [
                80, 
                1, 
                10, 
                6
            ], 
            "price": 10, 
            "profit": 40, 
            "sales": "2400"
        }
    ], 
    [
        "C623", 
        {
            "alist": [
                100, 
                10, 
                30, 
                50
            ], 
            "price": 80, 
            "profit": 6, 
            "sales": "100"
        }
    ]
]



*最初、python3.5で作ったが、upの際の確認時はpython2.7
*クォート統一してなくてすんません。

#備考
#ラムダ式と関数の関係
def func(x):
    return x ** 2

func = lambda x: x ** 2
func(2) #4

#string処理
string.strip()#全部 空白 改行 削除
string.strip("\n\r")#両端でヒットするもの削除
string.rstrip("\n\r")#ケツでヒットするもの削除
11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9