通过子级进行Javascript递归,并以HTML形式显示



我想显示一个基于嵌套子值的结果。我使用递归函数。根据下面的示例结果,我遇到了如何将其显示为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));

最新更新