數據構造函數
人們需要停止寫入數據是這樣的:
const tree =
{ id: 1, parentId: null, children:
[ { id: 3, parentId: 1, children:
[ { id: 5, parentId: 3, children: [] } ] } ] }
,並使用數據構造
// "Node" data constructor
const Node = (id, parentId = null, children = Children()) =>
({ id, parentId, children })
// "Children" data constructor
const Children = (...values) =>
values
// write compound data
const tree =
Node (1, null,
Children (Node (3, 1,
Children (Node (5, 3)))))
console.log (tree)
// { id: 1, parentId: null, children: [ { id: 3, parentId: 1, children: [ { id: 5, parentId: 3, children: [] } ] } ] }
這可以讓你你的心從分離開始寫入數據詳細信息如是否{}
或[]
甚至x => ...
用於包含您的數據。我會更進一步,創建一個統一的界面,保證tag
字段 - 以便它可以稍後與其他通用數據區分
堆棧片段在下面的程序中執行輸出是完美的。它沒有關係什麼數據看起來當打印出來像 - 重要的是很容易爲我們人類閱讀我們的程序 /寫,並很容易爲我們的程序讀/寫
當/如果你需要它在一個特定的格式/形狀,強制它成爲然後;直到這一點,保持好的一個容易
const Node = (id, parentId = null, children = Children()) =>
({ tag: Node, id, parentId, children })
const Children = (...values) =>
({ tag: Children, values })
// write compound data
const tree =
Node (1, null,
Children (Node (3, 1,
Children (Node (5, 3)))))
console.log (tree)
// { ... really ugly output, but who cares !.. }
工作讓我們搜索
我們可以用一個簡單的loop
輔助函數寫search
- 但通知你在看什麼不是;幾乎沒有邏輯(使用單個三元表達式);沒有像for
/while
這樣的命令式結構或像i++
那樣的手動迭代器遞增;不使用像push
/unshift
這樣的變異函數或有效函數如.forEach
; .length
屬性或使用[i]
風格的查找直接索引讀取沒有無意義的檢查 - 它只是函數和調用;爲什麼是這樣的 - 我們不必擔心任何其他噪聲
const Node = (id, parentId = null, children = Children()) =>
({ tag: Node, id, parentId, children })
const Children = (...values) =>
({ tag: Children, values })
const tree =
Node (1, null,
Children (Node (3, 1,
Children (Node (5, 3)))))
const search = (id, tree = null) =>
{
const loop = (path, node) =>
node.id === id
? [path]
: node.children.values.reduce ((acc, child) =>
acc.concat (loop ([...path, node], child)), [])
return loop ([], tree)
}
const paths =
search (5, tree)
console.log (paths.map (path => path.map (node => node.id)))
// [ 1, 3 ]
所以search
返回陣列路徑,其中每個路徑是節點的陣列案子?在與X
ID的孩子出現在樹多個位置的情況下,所有路徑孩子將返回
const Node = (id, parentId = null, children = Children()) =>
({ tag: Node, id, parentId, children })
const Children = (...values) =>
({ tag: Children, values })
const tree =
Node (0, null, Children (
Node (1, 0, Children (Node (4, 1))),
Node (2, 0, Children (Node (4, 2))),
Node (3, 0, Children (Node (4, 3)))))
const search = (id, tree = null) =>
{
const loop = (path, node) =>
node.id === id
? [path]
: node.children.values.reduce ((acc, child) =>
acc.concat (loop ([...path, node], child)), [])
return loop ([], tree)
}
const paths =
search (4, tree)
console.log (paths.map (path => path.map (node => node.id)))
// [ [ 0, 1 ],
// [ 0, 2 ],
// [ 0, 3 ] ]
你不小心寫列表單子
列表monad編碼模糊計算的想法 - 也就是說,可以返回一個或多個結果的計算的想法。讓我們做一個小的改變我們的計劃 - 這是有利的,因爲List
是通用的,現在可以用來在我們的程序中的其他地方,這種計算是必不可少的
如果你喜歡這個解決方案,你可能會喜歡閱讀my other answers that talk about the list monad
const List = (xs = []) =>
({
tag:
List,
value:
xs,
chain: f =>
List (xs.reduce ((acc, x) =>
acc.concat (f (x) .value), []))
})
const Node = (id, parentId = null, children = Children()) =>
({ tag: Node, id, parentId, children })
const Children = (...values) =>
List (values)
const search = (id, tree = null) =>
{
const loop = (path, node) =>
node.id === id
? List ([path])
: node.children.chain (child =>
loop ([...path, node], child))
return loop ([], tree) .value
}
const tree =
Node (0, null, Children (
Node (1, 0, Children (Node (4, 1))),
Node (2, 0, Children (Node (4, 2))),
Node (3, 0, Children (Node (4, 3)))))
const paths =
search (4, tree)
console.log (paths.map (path => path.map (node => node.id)))
// [ [ 0, 1 ],
// [ 0, 2 ],
// [ 0, 3 ] ]
你可能會FF創建地圖的id更好 – epascarello
請讓您的片段** **可運行通過移除語法錯誤(''....並且這樣),分配初始反對變量等。 –
我已經將開始帖子編輯爲正確的格式。 – Lemmy