Array.prototype.find() を再帰的に使用して単一のオブジェクトを返すにはどうすればよいでしょうか? 質問する

Array.prototype.find() を再帰的に使用して単一のオブジェクトを返すにはどうすればよいでしょうか? 質問する

私が解決しようとしているより大きな問題は、次のデータからわかります。

var data = [
    { id: 1 },
    { id: 2 },
    { id: 3 },
    { id: 4, children: [
        { id: 6 },
        { id: 7, children: [
            {id: 8 },
            {id: 9 }
        ]}
    ]},
    { id: 5 }
]

findById(data, id)を返す関数を作りたいです{ id: id }。たとえば、findById(data, 8)は を返し{ id: 8 }、 はfindById(data, 4)を返す必要があります{ id: 4, children: [...] }

これを実装するために再帰的に使用しましたが、オブジェクトを一緒にマッシュし続けるArray.prototype.findと問題が発生しました。私の実装では、returnパス特定のオブジェクトに。

例えば、 を使用するとfindById(data, 8)パス{ id: 8 }

 { id: 4, children: [ { id: 6 }, { id: 7, children: [ { id: 8}, { id: 9] } ] }

代わりに、単純に返して欲しい

{ id: 8 }

実装 (Node.js v4.0.0)

jsfiddle

var data = [
    { id: 1 },
    { id: 2 },
    { id: 3 },
    { id: 4, children: [
        { id: 6 },
        { id: 7, children: [
            {id: 8 },
            {id: 9 }
        ]}
    ]},
    { id: 5 }
]

function findById(arr, id) {
    return arr.find(a => {
        if (a.children && a.children.length > 0) {
            return a.id === id ? true : findById(a.children, id)
        } else {
            return a.id === id
        }
    })
    return a
}

console.log(findById(data, 8)) // Should return { id: 8 }

// Instead it returns the "path" block: (to reach 8, you go 4->7->8)
//
// { id: 4,
//   children: [ { id: 6 }, { id: 7, children: [ {id: 8}, {id: 9] } ] }

ベストアンサー1

問題は、検索のバブルです。ネストされた構造内で ID が見つかった場合、コールバックは、検索の値として true と解釈される要素を返そうとします。

このfindメソッドは、配列内の各要素に対してコールバック関数を 1 回実行し、コールバックが true 値を返す要素が見つかるまで実行します。[翻訳]

find の代わりに、見つかった場合は短絡する再帰的な検索スタイルを使用することをお勧めします。

var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4, children: [{ id: 6 }, { id: 7, children: [{ id: 8 }, { id: 9 }] }] }, { id: 5 }];

function findById(data, id) {
    function iter(a) {
        if (a.id === id) {
            result = a;
            return true;
        }
        return Array.isArray(a.children) && a.children.some(iter);
    }

    var result;
    data.some(iter);
    return result
}

console.log(findById(data, 8));

おすすめ記事