簡體   English   中英

嵌套對象上的Javascript遞歸函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM