簡體   English   中英

通過按層次結構順序遞減百分比對元組列表進行排序

[英]Sort a list of tuples by descending percentage with hierarchical order

我正在嘗試按主導地位的順序(按百分比降序)對具有多個級別的成分聲明進行排序。

我正在使用Python,並且有一個元組列表,每個元組都有以下變量:(成分,百分比,childID,parentID)。

它來自看起來像這樣的數據,可以按任何順序輸入數據。 下面的列是成分/子成分,百分比,childID,parentID。

#Ing1   30%             1   0
#---Sub1    30%         2   1
#---Sub2    60%         3   1
#------Sub3     15%     4   3
#------Sub4     85%     5   3
#---Sub5    10%         6   1
#Ing2   10%             7   0
#Ing3   60%             5   0

我現有的代碼在一個類似於以下列表(輸入順序)的列表中將其輸出給我:

list = [(Ing1,30,1,0),(Sub1,30,2,1),(Sub2,60,3,1),(Sub3,15,4,3),(Sub4,85,5,3),(Sub5,10,6,1),(Ing2,10,7,0),(Ing3,60,5,0)]

我需要做的是對列表中的購買百分比進行降序排序,同時保持層次結構從低到高的完整性。 因此,首先是第3級成分(Sub3,Sub4),然后是下一級,然后是頂級。
子級別需要與其父級進行排序。

因此,對於上面的示例,我需要按照以下順序進行輸出:

> #Ing3 60%             5   0
> #Ing1 30%             1   0
> #---Sub2  60%         3   1
> #------Sub4   85%     5   3
> #------Sub3   15%     4   3
> #---Sub1  30%         2   1
> #---Sub5  10%         6   1
> #Ing2 10%             7   0

因此,列表應如下所示:

list = [(Ing3,60,5,0),(Ing1,30,1,0),(Sub2,60,3,1),(Sub4,85,5,3),(Sub3,15,4,3),(Sub1,30,2,1),(Sub5,10,6,1),(Ing2,10,7,0)]

用Python做到這一點的最優雅的方法是什么。 哦,還有另一個警告,因為我只能導入哪些模塊。 如果它不是一個包含的模塊,由於我的環境,我可能無法訪問它。

您可以使用這樣的生成器:

lst = [('Ing1',30,1,0),
       ('Sub1',30,2,1),
       ('Sub2',60,3,1),
       ('Sub3',15,4,3),
       ('Sub4',85,5,3),
       ('Sub5',10,6,1),
       ('Ing2',10,7,0),
       ('Ing3',60,5,0)]

def sort_hierarchical(lst, parent=0):
    # sort the current layer (excluding all other elements) by the second element
    res = sorted([i for i in lst if i[3] == parent], key=lambda x: x[1], reverse=True)
    for item in res:
        yield item
        # recurse for all childs of this item
        for subitem in sort_hierarchical(lst, parent=item[2]):
            yield subitem

>>> list(sort_hierarchical(lst))
[('Ing3', 60, 5, 0),
 ('Ing1', 30, 1, 0),
 ('Sub2', 60, 3, 1),
 ('Sub4', 85, 5, 3),
 ('Sub3', 15, 4, 3),
 ('Sub1', 30, 2, 1),
 ('Sub5', 10, 6, 1),
 ('Ing2', 10, 7, 0)]

如果僅在將列表傳遞給函數之前對列表進行一次排序,則甚至可以進一步簡化。 然后,您只需要過濾項目,而無需多次對其進行排序:

def return_hierarchical(lst, parent=0):
    for item in (i for i in lst if i[3] == parent):
        yield item
        for subitem in return_hierarchical(lst, parent=item[2]):
            yield subitem

>>> list(return_hierarchical(sorted(lst, key=lambda x: x[1], reverse=True)))
[('Ing3', 60, 5, 0),
 ('Ing1', 30, 1, 0),
 ('Sub2', 60, 3, 1),
 ('Sub4', 85, 5, 3),
 ('Sub3', 15, 4, 3),
 ('Sub1', 30, 2, 1),
 ('Sub5', 10, 6, 1),
 ('Ing2', 10, 7, 0)]

在Python-3.3 +中,您可以使用yield from並將其縮短:

def return_hierarchical(lst, parent=0):
    for item in (i for i in lst if i[3] == parent):
        yield item
        yield from return_hierarchical(lst, parent=item[2])

一般注意事項:

我將您的list重命名為lst因此它不會lst內置list

您正在處理元組,但是您通過名稱引用它們,因此也可以使用collections.namedtuple 這還允許您通過屬性引用項目:

from collections import namedtuple

ingredient = namedtuple('Ingredient', ['ingredient', 'percentage', 'order', 'parent'])

lst = [ingredient('Ing1',30,1,0), ingredient('Sub1',30,2,1), ingredient('Sub2',60,3,1),
       ingredient('Sub3',15,4,3), ingredient('Sub4',85,5,3), ingredient('Sub5',10,6,1),
       ingredient('Ing2',10,7,0), ingredient('Ing3',60,5,0)]

def return_hierarchical(lst, parent=0):
    for item in (i for i in lst if i.parent == parent):
        yield item
        yield from return_hierarchical(lst, parent=item.parent)

list(sort_hierarchical(sorted(lst, key=lambda x: x.percentage, reverse=True)))

就我個人而言,我喜歡namedtuple但有些人則不喜歡,您說您受到導入的限制(盡管它在標准庫中,但仍然如此),所以我只在這里包括了它。

暫無
暫無

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

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