树结构处理最佳实践

最近实际开发过程中经常遇到需要处理树形数据结构,每次都要写一遍递归,感觉比较麻烦,各个组员的写法也不统一,于是想自己写一套终极版本,希望能够兼顾复杂的业务场景和代码执行效率直接上代码和大家分享一下,欢迎指正。

 

 

/**
 * 
 * @param {Array} tree [{label,value,children}]
 * @param {Object} option 
 * { 	
 * labelKey String 将转换为label的键  default:'label'	
 * valueKey String 将转换为value的键  default:'value'	
 * childrenKey String 将转换为children的键 default:'children'	
 * clean Boolean 是否剔除其余属性,default:true		
 * getValue Function 用于获取value的函数,传入当前节点,优先级高于valueKey default:undefind	
 * getLabel Function 用于获取label的函数,传入当前节点,优先级高于labelKey default:undefind	
 * getChildren Function 用于获取label的函数,传入当前节点,优先级高于childrenKey default:undefind					
 * deep Number 转化树结构的深度,为0时转化所有,默认为0 default:0				
 * }
 * @param {Array} result  目标数组,不用传 default:[]
 * 此方法不会修改原数据,会返回一个新的数组		
 * example:	  	
 * initTree(data, { labelKey: 'region_name', valueKey: 'national_code', childrenKey: 'childn_ational' })
 */
export const initTree = (tree, option, result = []) => {
	const { labelKey = 'label', valueKey = 'value', childrenKey = 'children', clean = true, getValue, getLabel, getChildren, deep = 0 } = option;
	for (let i = 0; i < tree.length; i++) {
		result[i] = {
			label: getLabel ? getLabel(tree[i]) : tree[i][labelKey],
			value: getValue ? getValue(tree[i]) : tree[i][valueKey],
		};
		if (!clean) {
			result[i] = { ...tree[i], ...result[i] };
		}
		const _children = getChildren ? getChildren(tree[i]) : tree[i][childrenKey];
		if (deep !== 1 && _children && _children.length) {
			result[i].children = [];
			initTree(
				_children, 
				deep > 1 ? { ...option, deep: option.deep - 1 } : option, 
				result[i].children
			);
		}
	}
	
/**
 * 遍历树结构,fn一旦返回false就会停止遍历
 * @param {Array} tree 树结构
 * @param {Function} fn 对每个节点执行一遍fn方法 
 * @param {String} childrenKey  作为children的键
 */
export const treeForEach = (tree, fn, childrenKey = 'children') => {
	for (let i = 0; i < tree.length; i++) {
		if (fn(tree[i]) === false) return false;
		if (
			tree[i][childrenKey] 
			&& tree[i][childrenKey].length 
			&& treeForEach(tree[i][childrenKey], fn) === false
		) return false;
	}
};
/**
 * 从树结构里根据value找到第一个结点
 * @param {*} value 
 * @param {Array} tree [{label,value,children}]
 */
export const findNodeByValue = (tree, value) => {
	let result;
	treeForEach(tree, (node) => {
		if (node.value === value) {
			result = node;
			return false;
		}
	});
	return result;
};
/**
 * 从树结构里根据label找到第一个结点
 * @param {*} value 
 * @param {Array} tree [{label,value,children}]
 */
export const findNodeByLabel = (tree, label) => {
	let result;
	treeForEach(tree, (node) => {
		if (node.label === label) {
			result = node;
			return false;
		}
	});
	return result;
};
return result;
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值