我正在嘗試將陣列陣列轉換為 JavaScript 中的嵌套物件陣列。假設陣列中的每個子陣列都代表一個檔案路徑。我想創建一個物件陣列,其中每個物件都有 2 個屬性、當前檔案的名稱以及當前檔案/父級之后的任何檔案/子級。
例如,如果我有這個陣列陣列,其中每個子陣列代表一個檔案路徑:
[['A', 'B', 'C'], ['A', 'B', 'D'], ['L', 'M', 'N']]
我想得到這個結果:
[
{
name :'A',
children: [
{
name: 'B',
children: [
{
name: 'C',
children: []
},
{
name: 'D',
children: []
}
]
}
]
},
{
name: 'L',
children: [
{
name: 'M',
children: [
{
name: 'N',
children: []
}
]
}
]
}
]
我嘗試通過陣列進行映射,并為當前檔案/父級創建一個物件(如果尚未創建)。我想我可能走在正確的軌道上,但我似乎想不出最好的方法。
uj5u.com熱心網友回復:
我可以在 5 分鐘內完成的事情,它可能可以改進。我相信這也可以寫成遞回函式。
const result = [];
arr.forEach((subArr) => {
var ref = result;
subArr.forEach((name) => {
const obj = ref.find((obj) => obj.name == name);
if (obj) {
ref = obj.children;
} else {
ref.push({ name, children: [] });
ref = ref[ref.length - 1].children;
}
});
});
uj5u.com熱心網友回復:
這是我的:
// Function to convert path array ‘a’ from position ‘i’ into tree structure in ‘v’.
const tree = (a, i, v) => {
if (i < a.length) { tree(a, i 1, v[a[i]] ||= { }) }
}
// Function to convert a simple node into the desired record format.
const record = (v) => {
const a = [];
for (const [k, w] of Object.entries(v)) {
a.push({ name: k, children: record(w) });
}
return a;
}
const m = { }
for (const a of [['A', 'B', 'C'], ['A', 'B', 'D'], ['L', 'M', 'N']]) {
tree(a, 0, m);
}
const result = record(m);
uj5u.com熱心網友回復:
雖然這個要求可能有點過頭了,但我有一個實用函式的變體,setPath用于將這樣的路徑添加到現有陣列。這與其他答案有點不同,因為它以不可變的方式執行此操作,回傳一個與原始物件共享盡可能多結構的新物件。我總是喜歡使用不可變資料。
使用它,我們可以撰寫一個hydrate函式來完成這項作業作為單線,const hydrate = (paths) => paths .reduce (setPath, []).
這在這里很可能是矯枉過正,因為可能沒有理由一個接一個地構建您的輸出不可變級別。但它證明了保持實用功能方便的價值。
代碼如下所示:
const call = (fn, ...args) => fn (...args)
const setPath = (xs, [name, ...names]) => call (
(i = ((xs .findIndex (x => x .name == name) 1) || xs .length 1) - 1) =>
name == undefined
? [...xs]
: [
...xs .slice (0, i),
{name, children: setPath ((i == xs .length) ? [] : xs [i] .children, names)},
...xs .slice (i 1)
]
)
const hydrate = (paths) => paths .reduce (setPath, [])
console .log (
hydrate ([['A', 'B', 'C'], ['A', 'B', 'D'], ['L', 'M', 'N']])
)
.as-console-wrapper {max-height: 100% !important; top: 0}
我們有一個簡單的call輔助函式,我在這里使用它來避免陳述句。盡可能地,我更喜歡使用運算式,因為它們避免了陳述句帶來的代碼中的時間概念,并且它們可以更好地組合成更大的部分。我們也可以使用默認引數來執行此操作,但它們還有其他問題。一個簡單的call函式可以很好地處理這個問題。
在我們的 main 函式中,我們將輸入中的名字與其余的名字分開。然后我們傳遞給call一個函式,該函式計算輸入陣列中具有我們現有名稱的元素的索引。如果它不存在,則索引將是該陣列的長度。這可能過于棘手。 如果沒有元素匹配則findIndex回傳。-1我們添加1到結果中,然后,如果是0,我們選擇比陣列長度多一個。最后我們從結果中減去1,現在索引將是我們找到目標的位置,或者如果沒有找到陣列的長度。
現在,如果路徑為空,我們回傳陣列的副本。(我更喜歡副本只是為了保持一致性,但直接回傳它是合法的。)如果它不為空,我們使用索引來拆分我們的輸入陣列,保留它之前的所有內容,為該索引構建一個新專案遞回呼叫setPath剩余的節點名稱,然后保留該索引之后的所有內容。
現在,如前所述,我們的hydrate函式是一個setPath從空陣列開始的簡單折疊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/523837.html
標籤:javascript数组算法javascript 对象
上一篇:如何在“M”大小的陣列中分配“n”個專案,以使元素均勻分布?
下一篇:什么時候應該在B樹中進行根分裂
