簡體   English   中英

按多個鍵/值對字典列表進行排序,其中值的順序應該是特定的

[英]Sort a list of dictionaries by multiple keys/values, where the order of the values should be specific

我有一個字典列表,並希望每個項目都按特定的屬性值排序。

名單:

[
{'name':'alpha', status='run'},
{'name':'alpha', status='in'}, 
{'name':'alpha-32', status='in'},
{'name':'beta', status='out'}
{'name':'gama', status='par'}
{'name':'gama', status='in'}
{'name':'aeta', status='run'}
{'name':'aeta', status='unknown'}
{'pname': 'boc', status='run'}
]

我知道我可以做到:

newlist = sorted(init_list, key=lambda k: (k['name'], k['status']) 

但還有兩個條件:

  1. 如果 dict 中不存在鍵name ,則要使用的名稱對應於pname鍵的值。
  2. status順序為['out', 'in', 'par', 'run']
  3. 如果status值與列表中的內容不對應,請忽略它 - 請參閱unknown

結果應該是:

[
{'name':'aeta', status='unknown'}
{'name':'aeta', status='run'}
{'name':'alpha', status='in'},
{'name':'alpha', status='run'},
{'name':'alpha-32', status='in'},
{'name':'beta', status='out'},
{'pname': 'boc', status='run'}
{'name':'gama', status='in'},
{'name':'gama', status='par'}
]

第一個條件很簡單,您將排序元組的第一個值默認為pname ,即

lambda k: (k.get('name', k.get('pname')), k['status'])

對於第二條和第三條規則,我將為狀態定義一個訂單字典

status_order = {key: i for i, key in enumerate(['out', 'in', 'par', 'run'])}

然后在 key-function 中使用它

lambda k: (k.get('name', k.get('pname')), status_order.get(k['status']))

我還沒有測試它,所以它可能需要一些調整

利用

from itertools import count
# Use count() instead of range(4) so that we
# don't need to worry about the length of the status list.

newlist = sorted(init_list,
                 key=lambda k: (k.get('name', k.get('pname')),
                                dict(zip(['out', 'in', 'par', 'run'], count())
                                    ).get(k['status'], -1)
                                )
                )

如果k['name']沒有退出,則回退到k['pname'] (如果不存在則返回None )。 同樣,如果給定狀態沒有已知的 integer,則默認為 -1。

我特意將這一切放在一個邏輯行中,以證明此時,您可能只想使用def語句定義key function。

def list_order(k):
    name_to_use = k.get('name')
    if name_to_use is None:
        name_to_use = k['pname']  # Here, just assume pname is available

    # Explicit definition; you might still write
    # status_orders = dict(zip(['out', ...], count())),
    # or better yet a dict comprehension like
    # { status: rank for rank, status in enumerate(['out', ...]) }
    status_orders = {
        'out': 0,
        'in': 1,
        'par': 2,
        'run': 3
    }

    status_to_use = status_orders.get(k['status'], -1)

    return name_to_use, status_to_use

newlist = sorted(init_list, key=list_order)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM