Skip to content

flatToTree

扁平化数据结构树形

参数

参数名参数类型参数说明
targetRecord<string, unknown>[]扁平化数据结构
options?Partial<Record<'idKey' | 'pidKey' | 'childrenKey' | 'topVal', string>>树形结构关键 keys(唯一标志、 父级id、 子集 keytopVal顶层值)

使用

ts
import  { flatToTree } from  "@manzhixing/utilsxy"
const provinceFlat = [
  {
    id: '1000',
    label: '湖北省',
  },
  {
    id: '1200',
    value: '江苏省',
    label: '江苏省',
  },
  {
    id: '1001',
    pid: '1000',
    label: '武汉',
  },
  {
    id: '1020',
    pid: '1000',
    label: '咸宁',
  },
  {
    id: '1022',
    pid: '1000',
    label: '孝感',
  },
  {
    id: '1034',
    pid: '1000',
    label: '襄阳',
  },
  {
    id: '1003',
    pid: '1000',
    label: '宜昌',
  },
  {
    id: '1201',
    pid: '1200',
    label: '南京',
  },
  {
    id: '1202',
    pid: '1200',
    label: '苏州',
  },
  {
    id: '1204',
    pid: '1200',
    label: '扬州',
  },
  {
    id: '100101',
    pid: '1001',
    label: '洪山区',
  },
  {
    id: '100102',
    pid: '1001',
    label: '武昌区',
  },
  {
    id: '100103',
    pid: '1001',
    label: '汉阳区',
  },
];
const provinceList = flatToTree(provinceFlat);

// 返回值
[
  {
    id: '1000',
    label: '湖北省',
    children: [
      {
        id: '1001',
        pid: '1000',
        label: '武汉',
        children: [
          { id: '100101', pid: '1001', label: '洪山区' },
          { id: '100102', pid: '1001', label: '武昌区' },
          { id: '100103', pid: '1001', label: '汉阳区' },
        ],
      },
      { id: '1020', pid: '1000', label: '咸宁' },
      { id: '1022', pid: '1000', label: '孝感' },
      { id: '1034', pid: '1000', label: '襄阳' },
      { id: '1003', pid: '1000', label: '宜昌' },
    ],
  },
  {
    id: '1200',
    value: '江苏省',
    label: '江苏省',
    children: [
      { id: '1201', pid: '1200', label: '南京' },
      { id: '1202', pid: '1200', label: '苏州' },
      { id: '1204', pid: '1200', label: '扬州' },
    ],
  },
]
ts
/*
 * @Author: Chengbotao
 * @Contact: https://github.com/chengbotao
 */

export function flatToTree(
  target: Record<string, unknown>[],
  options?: Partial<Record<'idKey' | 'pidKey' | 'childrenKey' | 'topVal', string>>
) {
  const copyFlat = Array.prototype.slice.call(target);
  const record: Record<string, unknown> = Object.create(null);
  const defaultOpts = Object.assign(
    {
      idKey: 'id',
      pidKey: 'pid',
      childrenKey: 'children',
      topVal: '',
    },
    options
  );
  const { idKey, pidKey, childrenKey, topVal } = defaultOpts;
  const tree = [];
  for (let i = 0, len = copyFlat.length; i < len; i++) {
    const item = copyFlat[i];
    const { [idKey]: idVal, [pidKey]: pidVal } = item;
    record[idVal] = item;

    if (pidVal && pidVal !== topVal) {
      if (pidVal in record) {
        const parentRecord = record[pidVal] as Record<string, unknown>;
        parentRecord[childrenKey] = parentRecord[childrenKey] || [];
        (parentRecord[childrenKey] as Record<string, unknown>[]).push(item);
      } else {
        console.error(`没有找到 id: ${pidVal} 顶级节点, 检查数据是否有误`);
      }
    } else {
      tree.push(item);
    }
  }
  return tree;
}