javascript - 如何在 JavaScript 中创建 'multi depth' 选择

标签 javascript arrays object recursion

我有一个对象数组,我想知道如何将其格式化为一个选择框,使用连字符来表示更深的每个级别。这是我的对象 -

let elements = {
  0: {
    id: 1,
    name: 'Parent folder',
    parent_id: null
  },
  1: {
    id: 2,
    name: 'Another parent folder',
    parent_id: null
  },
  2: {
    id: 3,
    name: 'Child folder 1',
    parent_id: 1
  },
  3: {
    id: 4,
    name: 'Child folder 2',
    parent_id: 1
  },
  4: {
    id: 5,
    name: 'Child of a child',
    parent_id: 4,
  },
}

我希望 elements 像下面这样重新格式化 -

let elements = {
  0: {
    id: 1,
    name: 'Parent folder',
    parent_id: null,
    depth: 0
  },
  1: {
    id: 3,
    name: 'Child folder 1',
    parent_id: 1,
    depth: 1
  },
  2: {
    id: 4,
    name: 'Child folder 2',
    parent_id: 1,
    depth: 1
  },
  3: {
    id: 5,
    name: 'Child of a child',
    parent_id: 4,
    depth: 2
  },
  4: {
    id: 2,
    name: 'Another parent folder',
    parent_id: null,
    depth: 0
  },
}

这样我就可以遍历对象并根据深度变量在以下结构中生成一个选择 -

Parent folder
- Child folder 1
- Child folder 2
-- Child of a child
Another parent folder

目前我正在通过一个过程循环我的对象并获得一个多级对象,所以也许我只需要弄清楚如何将其转换回单个深度对象数组?

if(elements.length > 0) {
    for (let i = 0; i < elements.length; i++) {
        let obj = Object.assign({}, elements[i]);

        let depth = 0;
        obj.items = [];

        map[obj.id] = obj;

        let parent = obj.parent_id || '-';
        if (!map[parent]) {
            map[parent] = { items: [] }
        }
        map[parent].items.push(obj);
    }

    console.log(map);
    return map['-'].items;
}

我觉得对此有一个相对简单的答案,但我正在努力!期待您的想法,谢谢!

最佳答案

您可以先创建一棵树来反射(reflect)关系,然后构建一个平面数组,该数组后来成为一个对象。

function getTree(array) {
    var o = {};
    array.forEach(function ({ id, name, parent_id }) {
        Object.assign(o[id] = o[id] || {}, { id, name, parent_id });
        o[parent_id] = o[parent_id] || {};
        o[parent_id].children = o[parent_id].children || [];
        o[parent_id].children.push(o[id]);
    });
    return o.null.children;
}

function getFlat(array = [], level = 0) {
    return array.reduce((r, { id, name, parent_id, children }) =>
        r.concat({ id, name, parent_id, level }, getFlat(children, level + 1)), []);
}

var elements = { 0: { id: 1, name: 'Parent folder', parent_id: null }, 1: { id: 2, name: 'Another parent folder', parent_id: null }, 2: { id: 3, name: 'Child folder 1', parent_id: 1 }, 3: { id: 4, name: 'Child folder 2', parent_id: 1 }, 4: { id: 5, name: 'Child of a child', parent_id: 4 } },
    tree = getTree(Object.assign([], elements)),
    flat = getFlat(tree);

console.log(flat.map(({ name, level }) => '-'.repeat(level) + name).join('\n'));
console.log(Object.assign({}, flat));
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于javascript - 如何在 JavaScript 中创建 'multi depth' 选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50907102/

相关文章:

javascript - 如何使用 Javascript 检测路径之间的交叉点

c - 具有共享内存和信号量的多个灵活阵列成员或 VLA

arrays - 如何使用吗啡过滤mongo文档中的嵌入数组

javascript - 如何扩展所有 Sequelize 模型?

javascript - 欧芹验证和标签

javascript - 如何在 Javascript 的开发人员工具控制台上打印对象

javascript - 在css中选择Ul和LI

javascript - jQuery - 启用/禁用复选框状态后的按钮

javascript - 我无法访问我当前的元素

javascript - 为什么我应该返回对象的 JS 返回未定义?