0

现有如下的数据结构格式如下

[
  ["广东", "广州", "天河", "猎德"],
  ["广东", "广州", "越秀", "越秀山"],
  ["广东", "深圳", "南山", "深圳湾"],
  ["广东", "深圳", "福田", "中心公园"],
  ["广西", "桂林", "七星", "七星岩"],
  ["广西", "南宁", "江南", "江南水街"],
  ["广东", "深圳", "南山", "科技园"],
  ["广东", "广州", "天河", "冼村"],
  ["广东", "佛山", "顺德", "乐从"]
]

每一项分别对应 省份 / 城市 / 区域 / 地点
需要转换成的嵌套格式如下

[
  {
    label: "广东",
    value: "广东",
    children: [
      {
        label: "广州",
        value: "广州",
        children: [
          {
            label: "天河",
            value: "天河",
            children: [
              { label: "猎德", value: "猎德" },
              { label: "冼村", value: "冼村" }
            ]
          },
          {
            label: "越秀",
            value: "越秀",
            children: [{ label: "越秀山", value: "越秀山" }]
          }
        ]
      },
      {
        label: "深圳",
        value: "深圳",
        children: [
          {
            label: "南山",
            value: "南山",
            children: [
              { label: "深圳湾", value: "深圳湾" },
              { label: "科技园", value: "科技园" }
            ]
          },
          {
            label: "福田",
            value: "福田",
            children: [{ label: "中心公园", value: "中心公园" }]
          }
        ]
      },
      {
        label: "佛山",
        value: "佛山",
        children: [
          {
            label: "顺德",
            value: "顺德",
            children: [{ label: "乐从", value: "乐从" }]
          }
        ]
      }
    ]
  },
  {
    label: "广西",
    value: "广西",
    children: [
      {
        label: "桂林",
        value: "桂林",
        children: [
          {
            label: "七星",
            value: "七星",
            children: [{ label: "七星岩", value: "七星岩" }]
          }
        ]
      },
      {
        label: "南宁",
        value: "南宁",
        children: [
          {
            label: "江南",
            value: "江南",
            children: [{ label: "江南水街", value: "江南水街" }]
          }
        ]
      }
    ]
  }
];

规则描述:

  1. 城市省份 的 children 下
  2. 区域城市 的 children 下
  3. 地点区域 的 children 下

边界情况:
城市名/区域名/地点名 不是唯一的,比如

  1. 广州多个区都有棠下
  2. 广东在广州/江门都有棠下
  3. 广西桂林七星有七星岩,广东肇庆同样有七星岩

想请教算法大佬们有什么处理的思路?

起初用Map去做,生成了一个类似于这样的Map,然后再遍历这个Map去生成最后的嵌套结构

clipboard.png

但是发现上述的边界情况并没有考虑到。

Z3ROG 15
2019-06-14 提问
3 个回答
0

已采纳
const list = [
  ['广东', '广州', '天河', '猎德'],
  ['广东', '广州', '越秀', '越秀山'],
  ['广东', '深圳', '南山', '深圳湾'],
  ['广东', '深圳', '福田', '中心公园'],
  ['广西', '桂林', '七星', '七星岩'],
  ['广西', '南宁', '江南', '江南水街'],
  ['广东', '深圳', '南山', '科技园'],
  ['广东', '广州', '天河', '冼村'],
  ['广东', '佛山', '顺德', '乐从'],
];

const result = list.reduce((res, arr) => {
  let _children = res;
  arr.forEach(value => {
    let _item = _children.find(v => v.value === value);
    if (!_item) {
      _item = {
        label: value,
        value: value,
        children: [],
      };
      _children.push(_item);
    }
    _children = _item.children;
  });
  return res;
}, []);

console.log(result);
0
      const data = [
        ['广东', '广州', '天河', '猎德'],
        ['广东', '广州', '越秀', '越秀山'],
        ['广东', '深圳', '南山', '深圳湾'],
        ['广东', '深圳', '福田', '中心公园'],
        ['广西', '桂林', '七星', '七星岩'],
        ['广西', '南宁', '江南', '江南水街'],
        ['广东', '深圳', '南山', '科技园'],
        ['广东', '广州', '天河', '冼村'],
        ['广东', '佛山', '顺德', '乐从'],
      ];

      const convert = data => {
        const map = {};

        const ret = [];

        data.forEach(coll => {
          let key = '';
          const list = [];

          for (let i = 0; i < coll.length; i++) {
            let item = coll[i];
            key += (i === 0 ? '' : '-') + item;
            map[key] = map[key] || {
              label: item,
              value: item,
              key: key,
            };

            list.push(map[key]);
          }

          ret.push(list);
        });

        ret.forEach(list => {
          list.forEach((item, index) => {
            if (index === 0) {
              return;
            }

            const parent = map[list[index - 1].key];

            parent.children = parent.children || [];

            if (!parent.children.find(v => v.key === item.key)) {
              parent.children.push(item);
            }
          });
        });

        const obj = Object.keys(map)
          .filter(key => key.split('-').length === 1)
          .map(key => map[key]);
        console.log(obj);
      };

      convert(data);
0

可以用原始数据构造出下面这种数据结构

{
    ["广东"]: {
        ["广州"]: {
            ["天河"]: {
                ["猎德"]: false,
                ["冼村"]: false
            }
        },
        ["深圳"]:{
            //...
        }
    },
    ["广西"]: {
        //...
    }
}

再转换成需要的对象,这样重名地区就不会有冲突了


实现如下

const data = [
    ["广东", "广州", "天河", "猎德"],
    ["广东", "广州", "越秀", "越秀山"],
    ["广东", "深圳", "南山", "深圳湾"],
    ["广东", "深圳", "福田", "中心公园"],
    ["广西", "桂林", "七星", "七星岩"],
    ["广西", "南宁", "江南", "江南水街"],
    ["广东", "深圳", "南山", "科技园"],
    ["广东", "广州", "天河", "冼村"],
    ["广东", "佛山", "顺德", "乐从"]
];

function combine(provinces, [province, city, district, _location]) {
    let cities = provinces[province];
    if (!cities) {
        cities = {};
        provinces[province] = cities;
    }
    let districts = cities[city];
    if (!districts) {
        districts = {};
        cities[city] = districts;
    }
    let locations = districts[district];
    if (!locations) {
        locations = {};
        districts[district] = locations;
    }
    locations[_location] = false;
}

function assignNode(collection, map) {
    for (let i in map) {
        const node = {label: i, value: i};
        collection.push(node);
        const values = map[i];
        if (values) {
            let children = [];
            node.children = children;
            assignNode(children, values)
        }
    }
}

function trans(data) {
    const provinces = [];
    data.forEach(e => combine(provinces, e));
    const result = [];
    assignNode(result, provinces);
    return result;
}

console.log(trans(data))

实际上不构造那种数据结构,由上往下一级一级合并也是可行的,就是判断是新增节点还是合并的逻辑会麻烦一点


const data = [
    ["广东", "广州", "天河", "猎德"],
    ["广东", "广州", "越秀", "越秀山"],
    ["广东", "深圳", "南山", "深圳湾"],
    ["广东", "深圳", "福田", "中心公园"],
    ["广西", "桂林", "七星", "七星岩"],
    ["广西", "南宁", "江南", "江南水街"],
    ["广东", "深圳", "南山", "科技园"],
    ["广东", "广州", "天河", "冼村"],
    ["广东", "佛山", "顺德", "乐从"]
];
function convert([province, city, district, _location]) {
    return {
        label: province,
        value: province,
        children: [
            {
                label: city,
                value: city,
                children: [
                    {
                        label: district,
                        value: district,
                        children: [
                            {
                                label: _location,
                                value: _location
                            }
                        ]
                    }
                ]
            }
        ]
    }
}
function merge(nodes, node) {
    let found = nodes.find(e => e.label === node.label);
    if (!found) {
        nodes.push(node);
        return;
    }
    const children1 = found.children;
    const children2 = node.children;
    if (children1 && children2) {
        merge(children1, children2[0])
    }
}

const res = data.map(convert).reduce((result, item) => {
    merge(result, item);
    return result;
}, []);

console.log(res)

这种方法由于会反复执行很多次Array.prototype.find()方法,在效率上会比前一种低一些,如果数据量不是特别大的话这个效率差可以忽略

撰写答案

推广链接