简体   繁体   English

如何对嵌套列表中的每个元素都符合的嵌套列表进行排序

[英]How can I sort a nested list accordign to each element in nested lists

I have a model Page which stores an optional parent page (instance of itself). 我有一个模型页面,该页面存储一个可选的父页面(本身的实例)。 In my views I made a function which will return a nested list of all pages and their parents. 在我看来,我做了一个函数,它将返回所有页面及其父页面的嵌套列表。

For example, my page architecture is 例如,我的页面架构是

CCC
  AAA
    DDD
    KKK
      EEE
ZZZ
  BBB

So DDD has the parent page AAA, which has it's own parent page CCC. 因此DDD具有父页面AAA,而后者具有自己的父页面CCC。 The CCC is top page and has no parent page. CCC是首页,没有父页面。

The function will first get a queryset of all instances of Pages and sort them alphabetically. 该函数将首先获取所有Pages实例的查询集,并按字母顺序对它们进行排序。 Then it will proceed to recursively generate a "full parent architecture" list, where each element on that list is another list of all parent pages, including the page itself. 然后,它将继续递归生成“完整父体系结构”列表,其中该列表上的每个元素都是所有父页面(包括页面本身)的另一个列表。 From the example above if we take a slice of list for page DDD, it would return [CCC, AAA, DDD]. 在上面的示例中,如果我们为DDD页提取了一部分列表,则它将返回[CCC,AAA,DDD]。

My function currently returns a list like this for the above stated example: 对于上述示例,我的函数当前返回这样的列表:

[ 
  [CCC, AAA],
  [ZZZ, BBB],
  [CCC],
  [CCC, AAA, DDD],
  [CCC, AAA, KKK, EEE],
  [CCC, AAA, KKK],
  [ZZZ],
]

As you can see from the that list, all elements are sorted alphabetically according to the last element on that list. 从该列表中可以看到,所有元素均根据该列表中的最后一个元素按字母顺序排序。 Now I want to display all those parent pages on my front end to basically look like a sitemap and show the proper parent architecture of all Pages on my site that is sorted alphabetically according to each element in each nested list. 现在,我想在前端显示所有这些父页面,基本上看起来像一个站点地图,并显示我站点上所有页面的正确父体系结构,这些结构根据每个嵌套列表中的每个元素按字母顺序排序。 The end result would be: 最终结果将是:

[ 
  [CCC],
  [CCC, AAA],
  [CCC, AAA, DDD],
  [CCC, AAA, KKK],
  [CCC, AAA, KKK, EEE],
  [ZZZ],
  [ZZZ, BBB],
]

To put it simple, I want to go through each first element on each list and sort it alphabetically, then each second element and sort them as well, then third, then forth, and so on. 为了简单起见,我想遍历每个列表中的每个第一个元素,然后按字母顺序对其进行排序,然后对每个第二个元素进行同样的排序,然后是第三个,然后依次类推,依此类推。 Is there a way to do this? 有没有办法做到这一点?

EDIT: To avoid confusion here's my view: 编辑:为避免混淆,这是我的观点:

def page_list(request):


    # Fetch all pages and sort them alphabetically
    queryset = Page.objects.all().order_by("title")
    output = []

    # Generate list of pages and their parents
    for page in queryset:
        output.append(get_list_of_parents(page))

    context = {
        "title": "Page List",
        "page_list": output,
    }

    return render(request, template + '/page_list.html', context)

# Get an array of all parent instances of a Page model
def get_list_of_parents(page, list=None):

    current_page = page 
    parent_list = []    

    if list is not None:
        parent_list = list

    parent_list.append(current_page)

    if current_page.parent is not None:
        parent_list = get_list_of_parents(current_page.parent, parent_list)
    else:
        # if this is the last parent page, reverse the order of list to display list in form of parent path to child
        parent_list.reverse()

    return parent_list

Using a tree of Pages: 使用页面树:

I define this simple tree structure: 我定义了这个简单的树结构:

class Page(object):
    def __init__(self, name, children=None):
        self.name = name
        self.children = children or []

    def display(self, indent=""):
        child_repr = [child.display(indent=indent + "  ") for child in self.children]
        return indent + self.name + "\n" + "".join(child_repr)

    def __str__(self):
        return self.display()

The display and __str__ methods are used for printing. display__str__方法用于打印。

I can build your tree as a list of Pages: 我可以将您的树构建为页面列表:

tree = [
    Page("CCC", [
        Page("AAA", [
            Page("DDD"),
            Page("KKK", [
                Page("EEE")])])]),
    Page("ZZZ", [
        Page("BBB")])]

I can display the structure like this: 我可以显示如下结构:

for item in tree:
    print(item)

I get: 我得到:

CCC
  AAA
    DDD
    KKK
      EEE

ZZZ
  BBB

To traverse the tree, I define the following method: 为了遍历树,我定义了以下方法:

    def traverse(self, result, stack=None):
        stack = stack or []
        stack.append(self.name)
        result.append(list(stack))
        for child in self.children:
            child.traverse(result, stack)
        stack.pop()

Where result is the list to fill. result是要填充的列表。

Usage: 用法:

result = []
for item in tree:
    item.traverse(result)

import pprint

pprint.pprint(result)

I'll get: 我去拿:

[['CCC'],
 ['CCC', 'AAA'],
 ['CCC', 'AAA', 'DDD'],
 ['CCC', 'AAA', 'KKK'],
 ['CCC', 'AAA', 'KKK', 'EEE'],
 ['ZZZ'],
 ['ZZZ', 'BBB']]

Great! 大!

Take advantage of helper functions in itertools and do your sorting with a simple and highly efficient one-line comparison function. 利用itertools中的辅助函数,并通过简单高效的单行比较函数进行排序。

>>> import pprint
>>> from itertools import dropwhile, izip_longest
>>> pages = [['CCC', 'AAA'],
...          ['ZZZ', 'BBB'],
...          ['CCC'],
...          ['CCC', 'AAA', 'DDD'],
...          ['CCC', 'AAA', 'DDD', 'EEE'],
...          ['CCC', 'AAA', 'KKK'],
...          ['ZZZ']]
>>> pprint.pprint(sorted(pages, cmp=lambda a, b: cmp(*next(dropwhile(lambda x: not cmp(x[0], x[1]), izip_longest(a, b))))))
[['CCC'],
 ['CCC', 'AAA'],
 ['CCC', 'AAA', 'DDD'],
 ['CCC', 'AAA', 'DDD', 'EEE'],
 ['CCC', 'AAA', 'KKK'],
 ['ZZZ'],
 ['ZZZ', 'BBB']]
>>>

This works not only for strings, but also Page instances, as long as they are comparable, ie that you have defined your __cmp__ method in your Page class. 只要它们是可比较的,这不仅适用于字符串,而且适用于Page实例,即您已经在Page类中定义了__cmp__方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM