我想显示一个基于嵌套子值的结果。我使用递归函数。根据下面的示例结果,我遇到了如何将其显示为HTML的问题。我正在使用React.js.
目前我正在使用console.log。这是我的代码:(样本数据在底部(
function recursion(data, label) {
if (!data) {
return;
}
for (let a = 0; a < data.length; a++) {
const item = data[a]
if (!item.items) {
const isLast = data.length - a === a
console.log(`(${item.course_id}) ${ isLast ? '' : label} `)
} else {
if (label) console.log(label)
recursion(item.items, item.type)
}
}
}
/*
Example result that I want to achieve is something like be:
(1894 $or 1501)
$or
(7068 $or 7120 or 7141)
$or
(997 $and 9001)
$or
(7256 $or 4534)
*/
//My sample data:
const data = [{
"type": "$or",
"items": [{
"course_id": "1894"
},
{
"course_id": "1501"
},
{
"type": "$or",
"items": [{
"course_id": "7068"
},
{
"course_id": "7120"
},
{
"course_id": "7141"
},
{
"type": "$and",
"items": [{
"course_id": "997"
},
{
"course_id": "9001"
}
]
}
]
},
{
"type": "$or",
"items": [{
"course_id": "7256"
},
{
"course_id": "4534"
}
]
}
]
}]
//start here
recursion(data)
将项中的所有叶节点(没有子节点的节点(放入一个数组中,然后递归到节点中。然后使用$类型将它们连接在一起。
const data = [{
"type": "$or",
"items": [
{
"course_id": "1894"
},
{
"course_id": "1501"
},
{
"type": "$or",
"items": [
{
"course_id": "7068"
},
{
"course_id": "7120"
},
{
"course_id": "7141"
},
{
"type": "$and",
"items": [
{
"course_id": "997"
},
{
"course_id": "9001"
}
]
}
]
},
{
"type": "$or",
"items": [
{
"course_id": "7256"
},
{
"course_id": "4534"
}
]
}
]
}]
/*
function recursion(data, label) {
if (!data) { return; }
for (let a = 0; a < data.length; a++) {
const item = data[a]
if (!item.items){
console.log(`${item.course_id} ${label} `)
} else {
console.log('')
console.log(label || '')
setParentLabel = item.type
const child = recursion(item.items, setParentLabel)
}
}
}
*/
const recursion = (data, label) => {
let nodes = [[]];
const type = data.type;
data.items.forEach( x => {
const leafs = nodes[0];
const isLeaf = !x.items;
if ( isLeaf ) leafs.push( x.course_id );
else nodes.push( recursion( x, x.type ) );
});
if ( nodes[0].length > 0 )
nodes[0] = '('+nodes[0].join(` ${type} `)+')';
else nodes = nodes.slice(1);
let string = '';
string = nodes.join(`n${type}n`);
return string;
};
console.log(recursion({items: data}))
const data = [{
"type": "$or",
"items": [
{
"course_id": "1894"
},
{
"course_id": "1501"
},
{
"type": "$or",
"items": [
{
"course_id": "7068"
},
{
"course_id": "7120"
},
{
"course_id": "7141"
},
{
"type": "$and",
"items": [
{
"course_id": "997"
},
{
"course_id": "9001"
}
]
}
]
},
{
"type": "$or",
"items": [
{
"course_id": "7256"
},
{
"course_id": "4534"
}
]
}
]
}]
/*
Example result that I want to achieve is something like be:
(1894 $or 1501)
$or
(7068 $or 7120 or 7141)
$or
(997 $and 9001)
$or
(7256 $or 4534)
*/
function recursion(data, label) {
if (!data) { return; }
let nodes = [[]];
let leafs = nodes[0];
for (let a = 0; a < data.length; a++) {
const item = data[a]
if (!item.items){
leafs.push(item.course_id)
} else {
setParentLabel = item.type
const child = recursion(item.items, setParentLabel)
nodes.push(child);
}
}
if ( nodes[0].length > 0 )
nodes[0] = '(' + nodes[0].join(` ${label} `) + ')';
else nodes = nodes.slice(1);
return nodes.filter(x=>!!x).join(`n${label}n`);
}
console.log(recursion(data))
const unSortedData = [{
"type": "$or",
"items": [{
"course_id": "1894"
},
{
"type": "$or",
"items": [{
"course_id": "7068"
},
{
"course_id": "7120"
},
{
"course_id": "7141"
},
{
"type": "$and",
"items": [{
"course_id": "997"
},
{
"course_id": "9001"
}
]
}
]
},
{
"type": "$or",
"items": [{
"course_id": "7256"
},
{
"course_id": "4534"
}
]
},
{
"course_id": "1501"
}
]
},
{
"type": "$or",
"items": [{
"course_id": "1894"
},
{
"type": "$or",
"items": [{
"course_id": "7068"
},
{
"course_id": "7120"
},
{
"course_id": "7141"
},
{
"type": "$and",
"items": [{
"course_id": "997"
},
{
"course_id": "9001"
}
]
}
]
},
{
"type": "$or",
"items": [{
"course_id": "7256"
},
{
"course_id": "4534"
}
]
},
{
"course_id": "1501"
}
]
}]
/**Inorder to split between two data I have used value.type if you want
*something else then you can use your own delimiter(just replace
*value.type with your requirement). Also if you want to store the looped
*item, you can store it into an array rather than returning string value.
*Example instead of dataJoiner you an use
*const arr = [];
*Inside forEach loop. arr.push(loopItems(value.items, value.type));
*and finally return arr. It's clearly upto you what you want to do with
*the recursed item
**/
function loopData(data) {
let dataJoiner = '';
data.forEach(value => {
dataJoiner = `${dataJoiner}n ${dataJoiner ? ' ' + value.type + ' ' : dataJoiner}n ${loopItems(value.items, value.type)})`;
});
console.log(dataJoiner);
return dataJoiner;
};
/** In this method items are sorted as per object type. Objects with only
*course_id are sorted and then Object with items are sorted. After that
*using
*reduce funtion it checks whether item has type and if it hasn't it
*accumulates by joining course_id with the given type. And whenever it
*detects type on the item it recursively calls loopItems whose result is
*accumulated into accumulator i.e. acc
**/
function loopItems(items, type) {
if(items && items.length) {
const sortedItems = items.sort((a, b) => Object.keys(a).length - Object.keys(b).length);
return sortedItems.reduce((acc, item, index) => {
if(item.type) {
return `${acc})n ${acc ? ' ' + type + ' ' : acc}n ${loopItems(item.items, item.type)}`;
}
const leftBracket = index === 0 ? '(' : ''
return `${leftBracket }${acc}${acc ? ' ' + type + ' ' : acc}${item.course_id}`;
}, '');
}
}
loopData(unSortedData);
function recursion(items, type = '') {
let result = [];
for (let item of items) {
if (!item.items && !item.type) {
result.push(item.course_id);
} else {
result.push(`(${recursion(item.items, item.type)})`);
}
}
return result.join(` ${type} `);
}
//start here
console.log(recursion(data));