Skip to content
Advertisement

How do I recursively use Array.prototype.find() while returning a single object?

The bigger problem I am trying to solve is, given this data:

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

I want to make a function findById(data, id) that returns { id: id }. For example, findById(data, 8) should return { id: 8 }, and findById(data, 4) should return { id: 4, children: [...] }.

To implement this, I used Array.prototype.find recursively, but ran into trouble when the return keeps mashing the objects together. My implementation returns the path to the specific object.

For example, when I used findById(data, 8), it returns the path to { id: 8 }:

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

Instead I would like it to simply return

{ id: 8 }

Implementation (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] } ] }

Answer

I would just use a regular loop and recursive style search:

function findById(data, id) {
    for(var i = 0; i < data.length; i++) {
        if (data[i].id === id) {
            return data[i];
        } else if (data[i].children && data[i].children.length && typeof data[i].children === "object") {
            findById(data[i].children, id);
        }
    }
}

//findById(data, 4) => Object {id: 4, children: Array[2]}
//findById(data, 8) => Object {id: 8}
Advertisement