Reputation: 6187
I have an object similar to this one:
const obj = {
operator: 'AND',
attributes: [
{
attribute: 'attr1',
value: '123'
},
{
attribute: 'attr2',
value: '234'
},
{
operator: 'OR',
attributes: [
{
attribute: 'attr3',
value: 'xxx'
}
]
}
]
}
And I want to construct a tree from it:
{
"id": "9aabbb89-cdef-4012-b456-7178a79bf800",
"type": "group",
"path": [
"9aabbb89-cdef-4012-b456-7178a79bf800"
],
"children1": {
"a89aaa88-0123-4456-b89a-b178a79c0aab": {
"type": "rule",
"id": "a89aaa88-0123-4456-b89a-b178a79c0aab",
"properties": {
"attribute": "attr1",
"value": "123"
},
"path": [
"9aabbb89-cdef-4012-b456-7178a79bf800",
"a89aaa88-0123-4456-b89a-b178a79c0aab"
]
},
"a9babbb8-cdef-4012-b456-7178a79c35ab": {
"type": "rule",
"id": "a9babbb8-cdef-4012-b456-7178a79c35ab",
"properties": {
"attribute": "attr2",
"value": "234"
},
"path": [
"9aabbb89-cdef-4012-b456-7178a79bf800",
"a9babbb8-cdef-4012-b456-7178a79c35ab"
]
},
"b9aaabb9-0123-4456-b89a-b178a79cc5c2": {
"type": "group",
"id": "b9aaabb9-0123-4456-b89a-b178a79cc5c2",
"properties": {
"conjunction": "OR"
},
"path": [
"9aabbb89-cdef-4012-b456-7178a79bf800",
"b9aaabb9-0123-4456-b89a-b178a79cc5c2"
],
"children1": {
"9baa88b9-cdef-4012-b456-7178a79cc5c3": {
"type": "rule",
"id": "9baa88b9-cdef-4012-b456-7178a79cc5c3",
"properties": {
"attribute": "attr3",
"value": "xxx"
},
"path": [
"9aabbb89-cdef-4012-b456-7178a79bf800",
"b9aaabb9-0123-4456-b89a-b178a79cc5c2",
"9baa88b9-cdef-4012-b456-7178a79cc5c3"
]
}
}
}
}
}
I write this code to create the tree:
function buildTree(obj) {
if (!obj || !Object.keys(obj).length) return {};
if ( 'attribute' in obj) {
const id = uuid4();
return {[id]: {
id,
type: 'rule',
properties: {
attribute: obj.attribute,
value: obj.value,
},
}
}
}
if (obj.operator === 'AND' || obj.operator === 'OR') {
return { id: uuid4(),
type: 'group',
properties: {
conjunction: obj.operator
},
children1: obj.operands.map(buildTree),
}
}
}
However, I'm stucked how to keep the track of the parent ids of a children and save them in a path
attribute. How can I fix that?
Upvotes: 0
Views: 67
Reputation: 136114
You have a recursive function, so just pass the path
down through the calls (starting with an empty array) and append to it as you go:
function buildTree(obj, path = []) {
if (!obj || !Object.keys(obj).length) return {};
const id = uuid4()
const newPath = [...path, id];
if ('attribute' in obj) {
return {
[id]: {
id,
type: 'rule',
path: newPath,
properties: {
attribute: obj.attribute,
value: obj.value,
},
}
}
}
if (obj.operator === 'AND' || obj.operator === 'OR') {
return {
id: id,
type: 'group',
path: newPath,
properties: {
conjunction: obj.operator
},
children1: obj.attributes.map(x => buildTree(x, newPath)),
}
}
}
const obj = {
operator: 'AND',
attributes: [{
attribute: 'attr1',
value: '123'
},
{
attribute: 'attr2',
value: '234'
},
{
operator: 'OR',
attributes: [{
attribute: 'attr3',
value: 'xxx'
}]
}
]
}
function uuid4() {
let array = new Uint8Array(16)
crypto.getRandomValues(array)
// Manipulate the 9th byte
array[8] &= 0b00111111 // Clear the first two bits
array[8] |= 0b10000000 // Set the first two bits to 10
// Manipulate the 7th byte
array[6] &= 0b00001111 // Clear the first four bits
array[6] |= 0b01000000 // Set the first four bits to 0100
const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
let idx = 0
return pattern.replace(
/XX/g,
() => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
)
}
console.log(buildTree(obj));
Upvotes: 1