就在最近,我寫了關于合并陣列和物件的第一個問題,并得到了很好的幫助。面對陣列和物件世界中的另一個挑戰,我之前從未處理過,我會大膽地再次詢問,并希望從如此好的答案中得到類似的結果。希望對其他觀眾也有幫助。
這樣做的目的是獲得帶有遞回子評論的評論。
作為示例資料,有一些帖子和評論被獲取。
let posts = [
{ id: '001a', topic: 'post topic', content: 'post content' }
]
let comments = [
{ id: '002a', post: '001a', parent: '001a', content: 'comment on post' },
{ id: '003a', post: '001a', parent: '002a', content: 'comment on comment' },
{ id: '004a', post: '001a', parent: '003a', content: 'comment on comments comment' },
]
如果我將其表述為文字,我會說:有條件地基于評論物件的父鍵,該物件應該成為其父評論物件的子評論物件。為了實作這一點,我開始認為它需要一個功能來創建另一個陣列。像:
let postComments = [
{
id: '002a',
post: '001a',
parent: '001a',
content: 'comment on post',
children: [
{
id: '003a',
post: '001a',
parent: '002a',
content: 'comment on comment',
children: [ {id: '004a', post: '001a', parent: '003a', content: 'comment on comments comment' }} ]
}
]
},
]
到目前為止,我嘗試的方法是在不創建這樣一個擴展自身的新陣列的情況下解決這個問題。更像是在每個塊中對其父級有條件地輸出評論。不幸的是,使用這種方法我找不到一種可擴展的方式/遞回地執行它 -我不確定這里的正確術語。這就是我現在提出這個問題的方法。由于我仍然不確定在擁有上述資料的情況下它是否是一個好的資料,因此非常歡迎任何關于此類問題的行之有效的方法的建議。
查看和理解上述場景的實作可能會提供足夠的清晰度,以便在更復雜的場景中使用它。我覺得這個問題已經變得更難了,不想讓它過于復雜。如果它對構建答案有影響,我正在研究并打算實作它的學習專案的實際代碼看起來更像下面的代碼片段。
顯示代碼片段
let posts = [
{
publicKey: { pubKeyObj1: {} },
post: { user: { userPubKeyObj1: {} }, topic: 'post topic', content: 'post content', timestamp: { ts: {} } }
}
]
let comments = [
{
publicKey: { pubKeyObj2: {} },
comment: { user: { userPubKeyObj2: {} }, post: { pubKeyObj1: {} }, parent: { pubKeyObj1: {} }, content: 'comment on post', timestamp: { ts: {} } }
},
{
publicKey: { pubKeyObj3: {} },
comment: { user: { userPubKeyObj1: {} }, post: { pubKeyObj1: {} }, parent: { pubKeyObj2: {} }, content: 'comment on comment', timestamp: { ts: {} } }
}
]
uj5u.com熱心網友回復:
let posts = [{ id: '001a', topic: 'post topic', content: 'post content' }]
let comments = [
{ id: '002a', post: '001a', parent: '001a', content: 'comment on post' },
{ id: '003a', post: '001a', parent: '002a', content: 'comment on comment' },
{ id: '004a', post: '001a', parent: '003a', content: 'comment on comments comment' },
]
function getNestedComments(parentId) {
const subComments = comments.filter((c) => c.parent === parentId)
if (subComments.length === 0) return subComments
subComments.forEach(c => {
c.children = getNestedComments(c.id)
})
return subComments
}
let postComments = getNestedComments('001a')
console.log(postComments)
打字稿游樂場
uj5u.com熱心網友回復:
這是另一個沒有遞回函式的解決方案。它使用地圖查找。
let posts = [
{ id: '001a', topic: 'post topic', content: 'post content' }
]
let comments = [
{ id: '002a', post: '001a', parent: '001a', content: 'comment on post' },
{ id: '003a', post: '001a', parent: '002a', content: 'comment on comment' },
{ id: '004a', post: '001a', parent: '003a', content: 'comment on comments comment' }
]
let postComments = toNestedComments(comments, posts[0].id);
console.log(postComments);
function toNestedComments(comments, postId) {
const nestedComments = [];
const map = {};
for (let i = 0; i < comments.length; i ) {
map[comments[i].id] = i;
}
for (let comment of comments) {
if (comment.parent === postId) {
nestedComments.push(comment);
} else {
if (!comments[map[comment.parent]].hasOwnProperty('children')) {
comments[map[comment.parent]].children = [];
}
comments[map[comment.parent]].children.push(comment);
}
}
return nestedComments;
}
uj5u.com熱心網友回復:
僅當您渲染該父級時才檢索屬于特定父級的注釋在我看來效率低下,因為每次您嘗試渲染代碼時都會遍歷您的所有注釋以找到屬于該父級的注釋。
更好的方法(在我看來)是為children每個帖子/評論添加一個屬性并填充它,就像您在代碼中所做的那樣。這里的困難在于以最小化必須“回圈”所有資料的次數來做到這一點。
一種方法是為每個帖子和評論建立一個查找表,如下所示:
const lookup = [...posts, ...comments].reduce((pre, cur) => {
cur.children = []; // Prepares an array to hold the children
pre[cur.id] = cur;
return pre;
}, {});
然后再次回圈評論,將它們自己添加到我們可以從查找表中讀取的父級中。
comments.forEach(c => lookup[c.parent].children.push(c));
由于 javascript 在物件方面的作業方式,這將導致原始專案posts和comments現在具有children填充該元素注釋的屬性(并且這些注釋具有自己的子級)。
現在您可以使用Post組件和svelte:self.
{#each children as child}
<svelte:self {...child} />
{/each}
該解決方案僅通過資料兩次來構建此結構(一次用于制作查找表,一次用于附加評論),因此比在渲染本身期間搜索評論更有效。
如果您的資料以始終在其父級之后出現評論的方式進行排序,則可以通過在構建地圖的同時推送到父級的子級來使這一點變得更好:
let map = [...posts, ...comments].reduce((pre, cur) => {
cur.children = [];
pre[cur.id] = cur;
if (cur.parent) pre[cur.parent].children.push(cur);
return pre;
}, {});
編輯以適合片段中提供的資料
const lookup = [...posts].reduce((pre, cur) => {
// Either a post or a comment
const item = cur.post ?? cur.comment;
// Prepares an array to hold the children
item.children = [];
pre[cur.publicKey] = item;
return pre;
}, {});
comments.forEach(({ comment }) => lookup[comment.post].children.push(comment));
不完美,但開始得到一個想法。這會將所有評論放在帖子上,因此評論沒有自己的孩子。
演示版
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/472041.html
標籤:javascript 数组 打字稿 目的 苗条
