I need to recursively add these comments in the correct order.
Currently i get an array of comments that are unsorted. These comments can be the top level or can be a child of the top level.
I was using this recursive method to add them but i can’t seem to get it right.
The result should be an array of CommentModal’s [CommentModal]
For reference:
The postID
is the topLevel
comment that the child belongs to. Every child comment will have a postID
so that they know where they belong to. If the child has a child, the top level child’s commentID
will be the child’s postID
.
Data and Data Models
struct Comment {
var postID: String
var commentID: String
var date: Double
}
class CommentModal {
var mainComment: Comment
var childComment: [CommentModal] = []
init(mainComment: Comment) {
self.mainComment = mainComment
}
}
let data: [Comment] = [
Comment(postID: "RootPostID", commentID: "116", date: 1),
Comment(postID: "RootPostID", commentID: "117", date: 2),
Comment(postID: "RootPostID", commentID: "118", date: 3),
Comment(postID: "116", commentID: "216", date: 4),
Comment(postID: "117", commentID: "217", date: 5),
Comment(postID: "118", commentID: "218", date: 6),
Comment(postID: "216", commentID: "316", date: 7),
Comment(postID: "216", commentID: "317", date: 8),
]
Initialized
private func index(comments: [Comment]) {
discardableCachedComments = comments
commentModalArray = addChildren(from: comments)
}
private func addChildren(from comments: [Comment]) -> [CommentModal] {
var result: [CommentModal] = []
for comment in comments {
let children = discardableCachedComments.filter { $0.postID == comment.commentID }
discardableCachedComments.removeAll { $0.postID == comment.commentID }
let commentModal = CommentModal(mainComment: comment)
if children.count >= 1 {
commentModal.childComment = addChildren(from: children)
}
discardableCachedComments.removeAll { $0.commentID == comment.commentID }
result.append(commentModal)
}
return result
}
Desired Output
Using the data
above i want to see the result be:
An array of 3 Top Level CommentModals.
Each of those Top Level CommentModals will have a childComment
which is an array of CommentModal
. For one of those childComment
we will also see it have two values in childComment
.
If you see the data you will see how the postID
and commentID
are assembled so that they are added correctly in its respective modal.
CodePudding user response:
I've changed a couple of names to make things semantically a little easier to understand, but this should show the gist of it. I've also changed CommentModal
into a struct
, since that made initialization easier, but you could change it back.
This should be copy/pastable into a Playground:
struct Comment : Codable {
var parentID: String
var id: String
var date: Double
}
struct CommentModel : Codable {
var comment: Comment
var children: [CommentModel] = []
}
let data: [Comment] = [
Comment(parentID: "RootPostID", id: "116", date: 1),
Comment(parentID: "RootPostID", id: "117", date: 2),
Comment(parentID: "RootPostID", id: "118", date: 3),
Comment(parentID: "116", id: "216", date: 4),
Comment(parentID: "117", id: "217", date: 5),
Comment(parentID: "118", id: "218", date: 6),
Comment(parentID: "216", id: "316", date: 7),
Comment(parentID: "216", id: "317", date: 8),
]
func createCommentModels(rootKey: String, input: [Comment]) -> [CommentModel] {
return input
.filter { $0.parentID == rootKey }
.map { comment in
return CommentModel(comment: comment,
children: createCommentModels(rootKey: comment.id,
input: input
))
}
}
func printModal(_ input: CommentModel, indent: Int = 0) {
let indentChars = Array(repeating: " ", count: indent).joined(separator: "")
print("\(indentChars)", input.comment.id)
if !input.children.isEmpty {
print("\(indentChars) - Children:")
input.children.forEach { printModal($0, indent: indent 4)}
}
}
let result = createCommentModels(rootKey: "RootPostID", input: data)
result.forEach {
printModal($0)
}
Which yields:
116
- Children:
216
- Children:
316
317
117
- Children:
217
118
- Children:
218