簡體   English   中英

Python:使用 lambda 函數按自定義順序按用戶定義對象對象的屬性排序

[英]Python: sort by attributes of a user-defined object object, in custom-defined order with a lambda function

我有一個自定義對象列表,它們具有兩個(重要)屬性、一個州代碼(TX、CA、NY 等)和一個年級(PK=preK、ES = 小學等)。 我需要按年級對這個列表進行排序,然后按州代碼的字母順序排序。 我現在擁有的是:

class myObject:
    def __init__(self, state, grade):
        self.state = state 
        self.grade = grade

myObjects = []
myObjects.append(myObject("KY", "HS"))
myObjects.append(myObject("AL", "ES"))
myObjects.append(myObject("NY", "PK"))
myObjects.append(myObject("CA", "PK"))

possibleGrades = ["PK", "K", "ES", "MS", "HS"]
myObjects.sort(key=lambda x: (x.grade, x.state))

for x in myObjects:
    print("Grade: {}, State: {}".format(x.grade, x.state))

輸出:

Grade: ES, State: AL
Grade: HS, State: KY
Grade: PK, State: CA
Grade: PK, State: NY

我想要的是:

Grade: PK, State: CA
Grade: PK, State: NY
Grade: ES, State: AL
Grade: HS, State: KY

我按年級對 myObjects 進行排序,然后說明,但把小學放在 PreK 之前,因為我不知道如何指定排序的順序為可能的等級。 我知道有一種方法可以使用 .index 就像在這里使用https://www.geeksforgeeks.org/python-sort-list-according-to-other-list-order/來按自定義順序排序,但我可以不知道如何使用對象的屬性來做到這一點。 看起來它應該是這樣的:

standards.sort(key=lambda x: (x.grade, x.state) possibleGrades.index(x))

或者,分兩次:

standards.sort(key=lambda x: x.grade possibleGrades.index(x))
standards.sort(key=lambda x: x.state)

但那些不起作用。 我知道您可以通過多次傳遞進行排序以按多個屬性進行排序,我不喜歡一次傳遞進行排序,這只是最近的一次迭代,它讓我覺得 Python 可能能夠做到這一點做。 在最壞的情況下,我可以用 def 編寫一個完整的函數來對其進行排序,但是在我這樣做之前,是否有更多的 Pythonic 方法可以像我試圖做的那樣使用 lambda 對其進行排序?

嘗試這個:

myObjects.sort(key=lambda x: (possibleGrades.index(x.grade), x.state))

這首先按possibleGrades Grades列表中的等級索引排序,然后按狀態排序。

正如@a_guest 所建議的,您還可以從列表中構建一個字典,特別是如果它是一個大列表,並進行 O(1) 查找。 然后代碼將如下所示:

grades = {g: i for i, g in enumerate(possibleGrades)}
myObjects.sort(key=lambda x: (grades[x.grade], x.state))

這是使用預構建排序字典和functools.partial將其放入 sort 的 1 參數鍵函數的答案。

    class myObject:
        def __init__(self, state, grade):
            self.state = state 
            self.grade = grade

    myObjects = []
    myObjects.append(myObject("KY", "HS"))
    myObjects.append(myObject("AL", "ES"))
    myObjects.append(myObject("NY", "PK"))
    myObjects.append(myObject("CA", "PK"))

    possibleGrades = ["PK", "K", "ES", "MS", "HS"]

    # grade sort attribute is their position in the list
    di_sort = {item: ix for ix, item in enumerate(possibleGrades)}

    print("di_sort:", di_sort)

    def key(x, di_sort):
        """ return a tuple of  (grade sort, state)"""
        return (di_sort.get(x.grade), x.state)


    # sort's `key` function parameter is only expected to take 
    # one parameter, an item in the list, so `key` needs adjusting

    from functools import partial

    key = partial(key, di_sort=di_sort)

    myObjects.sort(key=key)

    for x in myObjects:
        print("Grade: {}, State: {}".format(x.grade, x.state))

輸出:

di_sort: {'PK': 0, 'K': 1, 'ES': 2, 'MS': 3, 'HS': 4}
Grade: PK, State: CA
Grade: PK, State: NY
Grade: ES, State: AL
Grade: HS, State: KY

暫無
暫無

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

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