簡體   English   中英

如何使用特定規則使用 python 對元組進行排序

[英]How to sort tuple with python by using specific rules

我有這個元組:

[('site-nfv01-swsto01',), ('site-nfv01-swsto01V',),('site-nfv01-swsto02',),('site-nfv02-swsto02',), ('site-nfv02-swsto01',) , ('site-nfv02-swsto01V',)]

我想按以下順序對其進行分類:

site-nfv01-swsto01V
site-nfv01-swsto01
site-nfv01-swsto02
site-nfv02-swsto01V
site-nfv02-swsto01
site-nfv02-swsto02

有: [('site-nfv01-swsto01V',), ('site-nfv01-swsto01',),('site-nfv01-swsto02',),('site-nfv02-swsto01V',), ('site-nfv02-swsto01',), ('site-nfv02-swsto02',)]

574的想法是首先按升序對NFV部分進行分類,然后,我們也按升序對SWSTO進行分類,但是將以'V'結尾的SWSTO放在第一位

我怎樣才能做到這一點?

請注意,Python 已經自然地對元組進行了排序,首先對第一個元素進行排序,然后對第二個元素進行排序,等等。這意味着如果我們可以創建一個反映元素適當排名的元組,我們可以簡單地使用該元組作為鍵進行排序.

要將您的排序模式轉換為元組,請將“V”的存在視為負無窮大,否則使用該數字。

最后,我們可以使用 Python 的便利性,如zipre減少代碼行數。

import re
from math import inf
def sorted_tuples(string_list):
    def rank(chunk):
        if 'V' in chunk:
            return -inf
        return int(re.findall(r"\d+", chunk)[0])

    items = [(word, word.split('-')) for (word,) in string_list]
    keys = [(word, rank(chunks[1]), rank(chunks[2])) for (word, chunks) in items]
    keys.sort(key=lambda x: (x[1], x[2]))
    return list(zip(*keys))[0]


print(sorted_tuples([
     ('site-nfv01-swsto01V',), 
     ('site-nfv01-swsto01',),
     ('site-nfv01-swsto02',),
     ('site-nfv02-swsto01V',), 
     ('site-nfv02-swsto01',) , 
     ('site-nfv02-swsto02',)]))

# Outputs:
# ('site-nfv01-swsto01V', 
#     'site-nfv01-swsto01', 
#     'site-nfv01-swsto02', 
#     'site-nfv02-swsto01V', 
#     'site-nfv02-swsto01', 
#     'site-nfv02-swsto02'
# )

或者,對於單線(不要這樣做:):

lambda string_list: list(zip(*sorted([(word, list(map(lambda x: -inf \
     if 'V' in x else int(re.findall(r"\d+", x)[0]), word.split('-') \
     [1:]))) for (word,) in string_list], key=lambda x: x[1])))[0]

最好的方法是對sorted的 function 使用key參數。

來自文檔

key 參數的值應該是一個 function,它接受一個參數並返回一個用於排序目的的鍵。 這種技術很快,因為每個輸入記錄只調用一次鍵 function。

要對您的代碼列表進行排序,我會執行以下操作:

your_list = [('site-nfv01-swsto01',), ('site-nfv01-swsto01V',),('site-nfv01-swsto02',),('site-nfv02-swsto02',), ('site-nfv02-swsto01',) , ('site-nfv02-swsto01V',)]
#sort using key parameter
#key must be a function that returns a new value to be sorted
#this particular key function checks if 'V' is at the last position, 
#leaves the code unchanged if true,
#else adds arbitrary string at the end of the code that will cause the code to be sorted after codes with the same content at the beginning but lacking the 'V'
#in this case I chose 'z' which comes after 'v' in the alphabet
sorted_list = sorted(your_list, key=lambda code: code[0] if code[0][-1] == 'V'  else code[0]+'z')

如果您不知道 lambda 表達式如何工作,請查看文檔

我發現制作獨立鍵控 function 更清晰:

#!/usr/bin/env python

lst = [
    ("site-nfv01-swsto01",),
    ("site-nfv01-swsto01V",),
    ("site-nfv01-swsto02",),
    ("site-nfv02-swsto02",),
    ("site-nfv02-swsto01",),
    ("site-nfv02-swsto01V",),
]


def my_key(item):
    """Return a tuple that can be used for ordering the item."""

    first, middle, last = item[0].split("-")

    # For the middle part, what we really care about is the int after the "nfv" string.
    middle_int = int(middle[3:])

    # For the last part, we mostly care about the int after the "swsto" string...
    last_value = last[5:]

    # ...but not quite. Let's make sure that items with a trailing "V" sort lower than ones without
    # a "V".
    if last_value.endswith("V"):
        last_tuple = int(last_value[:-1]), "V"
    else:
        last_tuple = int(last_value), "z"

    # Python sorts tuples one component at a time, so return a tuple that can be compared against
    # the tuples generated for other values.
    return first, middle_int, last_tuple


# For demonstration purposes, show the sorting key generated for each item in the list.
for item in lst:
    print(item, my_key(item))

# Use that sorting key to actually sort the list.
print(sorted(lst, key=my_key))

這使您可以非常明確地了解排序鍵是如何生成的,因為它更容易測試。

暫無
暫無

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

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