问题
I am working on a Nodejs project. I have to create a function which takes an object (a child category) like:
{
id: 65,
name: 'Outdoor',
parent_id: 2
}
Now I want my function to check for the parent category by using parent_id
from database and return an array/object like this:
{
id: 2,
name: 'Furniture',
parent: {
id: 1,
name: 'Residential',
parent: {
id: ...,
name: ...,
parent: {
and so on..
}
}
}
}
This is what I have done so far:
* _get_category_parents(category, _array) {
if(_array === undefined) _array = []
if( category.parent_id !== 0 ) {
const c_parent = yield this.Database.from('categories').where('id', '=', category.parent_id)
_array.push({id: c_parent[0].id, name: c_parent[0].name})
yield this._get_category_parents(c_parent[0], _array)
}
return _array
}
And calling this function like this:
const parents = yield this._get_category_parents(category)
This returns me an array of parents like this:
[
{
"id": 2,
"name": "Furniture"
},
{
"id": 1,
"name": "Residential"
}
]
I want Residential object to be appended in Furniture's parent node.
I have spent too much time on this but not getting what I want. Any help would be deeply appreciated.
回答1:
What you want to think about is a recursive solution.
Since you're calling a database, it's probably unlikely, but if the lookup by id is synchronous, you might do it with code something like the following (note that I'm faking a db here):
const getHierarchy = (lookup, child) => {
const {id, name, parent_id} = lookup(child) ||
{id: null, name: null, parent_id: 0}
return parent_id == 0
? {id, name, parent_id}
: {...{id, name}, ...{parent: getHierarchy(lookup, {parent_id})}}
}
const items = [
{id: 1, name: 'Residential', parent_id: 5},
{id: 2, name: 'Furniture', parent_id: 1},
{id: 3, name: 'Other', parent_id: 0},
{id: 4, name: 'FooBar', parent_id: 3},
{id: 5, name: 'Stuff', parent_id: 0}
]
const lookup = child => items.find(item => item.id == child.parent_id)
const item = {id: 65, name: 'Outdoor', parent_id: 2}
console.log(getHierarchy(lookup, item))
You would have to write an appropriate lookup
function, presumably using this.Database.from(...)
. You might also want to simplified version that bakes in your lookup
function, in which case, you might write
const getAncestry = (item) => getHierarchy(lookup, item)
If, as seems more likely, your lookup is asynchronous, then that will affect getHierarchy
and how you call it. Here's one possibility:
const getHierarchy = async (lookup, child) => {
const {id, name, parent_id} = await lookup(child) ||
{id: null, name: null, parent_id: 0}
return parent_id == 0
? {id, name, parent_id}
: {...{id, name}, ...{parent: await getHierarchy(lookup, {parent_id})}}
}
const items = [
{id: 1, name: 'Residential', parent_id: 5},
{id: 2, name: 'Furniture', parent_id: 1},
{id: 3, name: 'Other', parent_id: 0},
{id: 4, name: 'FooBar', parent_id: 3},
{id: 5, name: 'Stuff', parent_id: 0}
]
const lookup = async child => new Promise(
(resolve, reject) => setTimeout(
() => resolve(items.find(item => item.id == child.parent_id)),
1000
)
)
const getAncestry = async item => getHierarchy(lookup, item)
const item = {id: 65, name: 'Outdoor', parent_id: 2}
getAncestry(item).then(console.log)
Note the change in how you call the function. You need to call .then()
on the resulting promise to get any useful behavior.
来源:https://stackoverflow.com/questions/48769989/create-javascript-object-having-nested-parent-objects