0

属性を持つコメントのリストがあります: pk(主キー)、parent_pk(親の主キー) など... ネストを考慮して表示したい — コメントに子がある場合は、コメントを表示し、次にインデントされた子を表示する. コメントが他のコメントpkと同じである場合、コメントは他のコメントの子ですparent_pk

本来は Django ブログで実装する予定ですが、まずはハウツーを学びたいと思います。そのため、簡単にするために、CLI アプリを作成しました。すぐに使えるソリューションがあることは知っていますが、自分でそれを行う方法を学びたいと思っています。:)

これは今のところ私のコードです:

class Comment(object):
    def __init__(self, pk, parent_pk, content):
        self.pk = pk
        self.parent_pk = parent_pk
        self.content = content

    def has_children(self, comments):
        for comment in comments:
            if self.pk == comment.parent_pk:
                return True
        return False

    def get_children(self, comments):
        children = []
        for comment in comments:
            if self.pk == comment.parent_pk:
                children.append(comment)
        return children


def print_nested(comments, level=0):
    def to_whitespaces(level):
        if level == 0:
            return ""
        else:
            return " " * (level * 2)

    for comment in comments:
        print to_whitespaces(level) + comment.content
        if comment.has_children(comments):
            print_nested(comment.get_children(comments), level + 1)
            comments.pop(0)

comments = [
    Comment(1, None, "foo"),
    Comment(2, 1, "foo bar"),
    Comment(3, None, "spam"),
    Comment(4, 3, "spam cheese"),
    Comment(5, 4, "spam cheese monty"),
    Comment(6, None, "muse"),
]

print_nested(comments)

これはSprunge.usにあります(構文付き)。

期待される結果:

foo
  foo bar
spam
  spam cheese
    spam cheese monty
muse

実結果:

foo
  foo bar
spam
  spam cheese
spam cheese monty
muse

ご覧のとおり、spam cheese montyまったくインデントされていません。それはなぜですか?どのように実装しますか?ありがとう!

4

3 に答える 3

1

再帰的に呼び出すprint_nested場合は、現在の要素の子である要素のみを使用して呼び出します。

だから、あなたがprint_nestedの子供たちを呼ぶspamとき、あなたはただを得るspam cheese

つまり、を呼び出すget_childrenと、渡すリストにspam cheese要素がないため、への最も外側の呼び出しのメンバーとしてのみ検出されるため、インデントされません。commentsspam cheese montyprint_nested

スクリプトの現在の構造を維持したい場合は、get_children再帰的にする必要があります。これにより、子の子が無限に検出されます。

より良い方法は、コメントから実際のツリーを構築することです。ここでは、リストの走査を行わなくても、実際に親のコメントを検索できます。

あなたの例で機能し、リストの代わりにツリーを使用するように簡単に変換できる簡単な方法:

class Comment(object):
    def __init__(self, pk, parent_pk, content):
        self.pk = pk
        self.parent_pk = parent_pk
        self.content = content

    def depth(self):
        depth = 0
        comment = self
        # this is just a recursive lookup converted to iterative
        while comment.parent_pk:
            # replace the array indexing with traversing up a tree
            comment = comments[comment.parent_pk - 1]
            depth += 1
        return depth

def print_nested(comments):
    for comment in comments:
        print comment.depth() * 2 * " " + comment.content

comments = [
    Comment(1, None, "foo"),
    Comment(2, 1, "foo bar"),
    Comment(3, None, "spam"),
    Comment(4, 3, "spam cheese"),
    Comment(5, 4, "spam cheese monty"),
    Comment(6, None, "muse"),
]

print_nested(comments)
于 2012-10-14T18:25:34.720 に答える
1

子をチェックして出力する再帰関数が必要なだけです。

class Comment(object):
    def __init__(self, pk, parent_pk, content):
        self.pk = pk
        self.parent_pk = parent_pk
        self.content = content



def print_nested(comments,pk=None,level=0):
    for comment in comments:
        if comment.parent_pk==pk:
            print ' ' * (level * 2), comment.content
            print_nested(comments,comment.pk,level+1)

comments = [
    Comment(101, None, "foo"),
    Comment(201, 101, "foo bar"),
    Comment(301, None, "spam"),
    Comment(415, 301, "spam cheese"),
    Comment(505, 415, "spam cheese monty"),
    Comment(622, None, "muse"),
]

print_nested(comments)
于 2012-10-14T18:53:04.710 に答える
0

Comment(3, None, "spam") の子として発生する Comment(4, 3, "spam Cheese") を表示すると、コメントからポップアウトされます。したがって、Comment(5, 4, "spam Cheese monty") を処理すると、親の "pk" が見つからないため、結果は root として表示されます

于 2012-10-14T18:10:32.300 に答える