Python列表的复杂排序算法?

时间:2011-08-19 17:15:33

标签: python list sorting

我需要订购一条list条评论,以便按顺序显示。

每条评论都有:

  • 热门家长评论(针对查询)
  • 家长评论
  • 缩进级别

如果我将评论作为list提取,那么最有效的排序方法是什么,以便每条评论低于其父

必须保留为一维列表。我只是想重新排列这些项目。我正在尝试这个,但它不起作用,因为列表在enumaration期间发生了变异,打破了反击:

i = 0;
for child in childList:
    ii = 0;
    for ch in childList:
        if (ch.reply == child.id):
            childList.insert(i+1, childList.pop(ii))

    ii += 1;
    i += 1;

2 个答案:

答案 0 :(得分:1)

所以...你有这样的东西吗?

class Comment(object):
    all_comments = []

    def __init__(self, message, parent):
        self.message = message
        self.parent = parent
        self.all_comments.append(self)

    def __iter__(self):
        """
        Yields tuples of (indentation level, comments), with this comment first
        and child comments later.
        """
        # what goes here?

这只是深度优先的预订树遍历。

import itertools

class Comment(object):
    def __iter__(self):
        return _iter_helper(self, 0)

    def _iter_helper(self, depth):
        item = {'indent_level': depth, 'comment': self}
        return itertools.chain([item], 
                               *[comment._iter_helper(depth+1)
                                 for comment 
                                 in self.all_comments
                                 if comment.parent == self])

正如Harypyon所说,存储孩子比查看父母然后计算孩子更有效地查看这个问题。

修改

  

我不认为使用MySQL可以存储孩子。

好的..这是在数据库中你(可能)想要一些产生所需结果的SQL吗?

你有一张类似这样的桌子吗?

CREATE TABLE comments (
    id INTEGER PRIMARY KEY,
    parent INTEGER,
    comment TEXT        
);

不幸的是,MySQL不支持递归查询语法(with recursive公用表表达式也不支持connect by),所以这个自引用模式虽然简单而优雅,但是如果你想要在具有任意深度和所有所需元数据的单个查询中完成整个事情。

有两种解决方案。首先,您可以通过在python中使用公共表查询等效来模拟递归查询,或者使用临时表在MySQL中模拟递归查询,每个子选择作为单独的实际查询。缺点是这既不优雅(许多SQL查询)而且浪费,(通过连接传输或存储在磁盘上的额外数据)。

另一个选择是接受注释树的传递闭包是不可计算的,但你仍然可以做出妥协。您很可能不希望(或需要)一次显示超过一百条注释,并且您同样不需要显示超过5层嵌套的深度。要获得更多信息,您只需使用不同的根注释运行相同的查询。因此,您最终会得到类似

的查询
SELECT c1.*, c2.*, c3.*, c4.*, c5.*
FROM comments c1
LEFT JOIN comments c2 ON c1.id = c2.parent
LEFT JOIN comments c3 ON c2.id = c3.parent
LEFT JOIN comments c4 ON c3.id = c4.parent
LEFT JOIN comments c5 ON c4.id = c5.parent
WHERE c1.parent = ?

这会给你一个很好的“批量”评论,最多5个级别。

答案 1 :(得分:0)

我建议您更改/创建一个Comment类,其中包含注释信息及其子项列表。然后循环遍历列表并创建注释字典为Comment个对象。再次循环,这次将每个注释添加到父对象。最后,循环遍历字典并选择没有父母的评论,这些是您的顶级评论。这些Comment对象包含对所有其他注释的引用!

这里有一些代码说明了我的意思,并将最终的评论对象放在一维列表中:

class Comment:
    def __init__(self, _id, parent):
        self.id, self.parent = _id, parent
        self.children = []

comments = [
    [1, None], # id, parent
    [2, 1],
    [3, None],
    [4, 2],
    [5, 3],
]

# store comments by their ID, as Comment objects
comments_dict = {}
for comment in comments:
    comments_dict[comment[0]] = Comment(*comment)

# store top level comments, and add child comments to their parent objects
top_comments = []
for _id, comment in comments_dict.items():
    if comment.parent != None:
        comments_dict[comment.parent].children.append(comment)
    else:
        top_comments.append(comment)

# final list of comments
comments = []
def add_comment(comment):
    """Recursively add comments to final list"""
    global comments
    comments.append(comment)
    if comment.children:
        for child in comment.children:
            add_comment(child)

for comment in top_comments:
    add_comment(comment)

print [comment.id for comment in comments]