[英]Javascript recursive function on nested object
我們有以下類型的對象:
const obj = {
a: { "=": 0 },
b: {
c: { "=": 1 },
d: {
e: { "=": 2 },
f: {
g: { "=": 3 }
}
}
}
}
我正在嘗試編寫一個函數,該函數返回一個帶有對象鍵的數組,包括嵌套的鍵,但是如果它們是嵌套的並且它們的值不是{ "=": "something" }
則對它們進行分組。 為了更好地解釋,我將編寫上述對象所需的示例輸出:
["a", "b.c", "b.d.e", "b.d.f.g"]
我現在所取得的只是一個只遍歷第一級的函數,但我承認我被困在遞歸部分,在該部分中,相同的函數將應用於對象的每個級別,直到它到達類型{ "=": "something" }
。 遵循我的實際代碼:
function nestedObject(obj) {
const operator = "="
const attributes = []
void (function traverse(obj) {
if (isObject(obj)) { // <-- isObject(obj) just checks if typeof obj == "object", !Array.isArray(obj), obj !== null
for (const [k,v] of Object.entries(obj)) {
let attr = k
for (const [k_,v_] of Object.entries(v)) {
if (operator !== k_) {
attr += "." + k_
// here is where the recursive part should start
// but I didn't figure out yet how to make it right.
// Of course calling traverse(v_) doesn't give the desired result.
}
attributes.push(attr)
}
}
}
})(obj)
console.log(attributes) // <-- will output ["a", "b.c", "b.d"]
}
我希望我解釋得足夠好。 我什至不知道這是否可能,但我認為這是可能的。 很想聽聽一些想法。
這是一個小的生成器函數,給定一個對象,遞歸地產生像[ array-of-nested-keys, value ]
這樣的對:
function* enumRec(obj, keys=[]) {
yield [keys, obj];
if (obj && typeof obj === 'object')
for (let [k, v] of Object.entries(obj))
yield *enumRec(v, keys.concat(k))
}
為了解決手頭的問題,迭代enumRec
並收集以 a =
結尾的鍵:
for (let [keys, _] of enumRec(obj)) {
if (keys.at(-1) === '=')
console.log(keys.slice(0, -1).join('.'))
}
我保留了一些實用功能,以使此類編碼更容易。 其中一個接受一個對象並列出該對象中的所有葉路徑,作為鍵數組。 在此基礎上構建您的函數只需刪除尾隨=
部分並用點連接結果:
const getPaths = (obj) => Object (obj) === obj ? Object .entries (obj) .flatMap (([k, v]) => getPaths (v) .map (p => [k, ...p])) : [[]] const nestedObject = (obj) => getPaths (obj) .map (p => p .at (-1) == '=' ? p .slice (0, -1): p) .map (p => p .join ('.')) const obj = {a: {"=": 0}, b: {c: {"=": 1}, d: {e: {"=": 2}, f: {g: {"=": 3}}}}} console .log (nestedObject (obj))
這是一個比我通常編寫的稍微復雜的getPaths
版本。 通常我會區分數字數組索引和字符串對象鍵,但這在這里不相關,所以這個版本被簡化了。
最重要的是,主要功能應該足夠清楚。
請注意,這並不禁止內部=
鍵,因此如果與輸入中的g
平行,您也有一個帶有=
鍵的h
,如下所示:
f: {
g: { "=": 3 },
h: { "=": {i: { "=": 4}}}
}
我們會產生這個結果:
["a", "b.c", "b.d.e", "b.d.f.g", "b.d.f.h.=.i"]
如果您還想刪除這些,可以在兩個map
調用之間添加:
.filter (p => ! p.includes ('='))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.