将 NSMutableArray 排序为线程注释

Sort NSMutableArray as threaded comments

我正在为网站开发一个 iOS 应用程序,它使用 disqus 评论系统。 所以我正在尝试添加功能以从此应用程序添加评论。

我的问题是我不知道如何保持线程结构,例如:

  1. Comment 1
    • Child 1.1
      • Child 1.1.1
      • Child 1.1.2
    • Child 1.2
      • Child 1.2.1
  2. Comment 2
    • Child 2.1

我在 Java 这里找到了解决方案 java solution

差不多可以了,但是有个大问题。 它使结构像这样:

  1. Comment 1
    • Child 1.1
    • Child 1.2
      • Child 1.2.1
      • Child 1.1.1
      • Child 1.1.2
  2. Comment 2
    • Child 2.1

破坏了parents和children的关系
当我添加一个新的child时,它只知道它的parent有多少child人,也就是说这个child有多少兄弟。 但是没有资料说这个child的兄弟还有children,也就是说我加一个新的child的时候并不知道他有侄子。

[threaded insertObject:child atIndex:i+[parent childCount]];

请帮帮我,我真的卡住了。

这里是link,用于测试项目link

下面是 objective-c

中对数组进行排序的代码
+ (NSMutableArray *)makeThreadedCommentsOutOf:(NSMutableArray *)comments{

    NSMutableArray *threaded = [[NSMutableArray alloc] initWithCapacity:0];

    //An array used to hold processed comments which should be removed at the end of the cycle
    NSMutableArray *removeComments = [[NSMutableArray alloc] initWithCapacity:0];

    //get the root comments first (comments with no parent)
    for(int i = 0; i < [comments count]; i++){
        Comment *comment = [comments objectAtIndex:i];
        if([[comment parentId] isEqual:[NSNull null]]){
            comment.commentDepth = 0;//A property of Comment to hold its depth
            comment.childCount = 0;
            [threaded addObject:comment];
            [removeComments addObject:comment];
        }
    }

    if([removeComments count] > 0){
        //clear processed comments
        [comments removeObjectsInArray:removeComments];
        [removeComments removeAllObjects];
    }

    int depth = 0;
    //get the child comments up to a max depth of 10
    while([comments count] > 0 && depth <= 10){
        depth++;
        for(int j = 0; j< [comments count]; j++){
            Comment *child = [comments objectAtIndex:j];
            //check root comments for match
            for(int i = 0; i < [threaded count]; i++){
                Comment *parent = [threaded objectAtIndex:i];
                if([[parent commentId] isEqualToString:[child parentId]]){
                    [parent setChildCount:[parent childCount]+1 ];
                    [child setCommentDepth:depth+[parent commentDepth]];
                    [threaded insertObject:child atIndex:i+[parent childCount]];
                    [removeComments addObject:child];
                    continue;
                    //break;
                }
            }
        }
        if([removeComments count] > 0){
            //clear processed comments
            [comments removeObjectsInArray:removeComments];
            [removeComments removeAllObjects];
        }
    }    
    return threaded;
}

虽然你没有这么说,但你的数组中的评论似乎已经按时间顺序排列了;那就是 children 发生在他们的 parents 和他们之前的任何兄弟姐妹之后。

您的问题是,评论不会紧跟在其前一个兄弟及其所有 children 之后,或者如果它是第一个 child,则不会紧跟在其 parent 之后。

你也没有说评论是否知道他们child人的commentID,但是你说他们知道他们parent的commentID

如果以上任何一条是错误的,那么其余答案可能对您没有帮助。假设它是正确的,请考虑以下粗略算法:

  1. 创建一个空数组来保存所有根评论,那些没有 parents.
  2. 创建一个空字典以将 parent commentID 映射到评论数组中的 child 索引数组。
  3. 逐一检查您的评论数组,依次检查每条评论。如果评论没有 parent ,请将其添加到您的根评论数组中。如果它有一个 parent 将评论的索引添加到您的字典中,它将 parent commentID 映射到 child 索引的数组。

使用这两种数据结构,您可以轻松地按照您希望的顺序遍历您的评论。您遍历根注释数组,并且对于每个注释,您通过遍历在字典中找到的 child 索引数组来遍历其 children。以此类推,递归。

如果您想要一个 "sorted" 数组,您可以使用上述递归算法创建它,无需尝试计算在现有可变数组中插入注释的位置 - 您发现这是一项具有挑战性的任务 -评论将按正确的顺序添加。

HTH

附录:对评论的回应

递归 是编程中的一个基本概念。在pseudo-code大纲中,上面描述的算法是:

visitAllDescendants(comment - the parent comment
                    allComments - indexed collection of all comments
                    parentToChildren - map from parentID to child comment indexes
                   )
{
   do something with comment - do whatever you want with the parent
   for every childIndex in order from parentToChildren[comment] do
      visitAllDescendants(allComments[childIndex], allComments, parentToChildren) - recursively process children
}

你会为你的每个根调用它。

如果您的 "do something with comment" 是将其添加到有序集合中,那么该算法将按照您想要的顺序生成评论集合。