Javascript Рекурсия через детей и отображение в HTML - PullRequest
1 голос
/ 21 апреля 2020

Я хочу отобразить результат, основанный на значении вложенных детей. Я использую функцию рекурсии для этого. У меня возникли проблемы с отображением значения 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)

Ответы [ 3 ]

1 голос
/ 21 апреля 2020

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);
1 голос
/ 21 апреля 2020

Помещает все конечные узлы (узлы без дочерних элементов) в элементы в массив, а затем возвращается в узлы. Затем соедините их все вместе, используя тип $.

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))
0 голосов
/ 21 апреля 2020
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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...