【问题标题】:Lodash re-assign array of objects to build a treeLodash 重新分配对象数组以构建树
【发布时间】:2016-10-18 15:55:15
【问题描述】:

有没有一种捷径可以将由对象组成的数组重新分配到一个新数组中。我想使用 Lodash 库,但不知道如何在内部拆分和连接。我需要这个来使用 jstree 库构建一棵树

我有这样的事情:

 [
      {
        'text':'parent 1',
        'children': [
          {
            'text':'children 3'
          }
        ]
      },
      {
        'text':'parent 2',
        'children': []
      },
      {
        'text':'parent 3',
        'children': []
      },
      {
        'text':'parent 1',
        'children': [
          {
            'text':'children 1',
            'children': []
          },
          {
            'text':'children 2',
            'children': []
          }
        ]
      }
    ] 

而我想在变身后拥有下一个

[
  {
    'text':'parent 2',
    'children': []
  },
  {
    'text':'parent 3',
    'children': []
  },
  {
    'text':'parent 1',
    'children': [
      {
        'text':'children 1',
        'children': []
      },
      {
        'text':'children 2',
        'children': []
      },
      {
        'text':'children 3'
      }
    ]
  }
] 

如果“文本”相同,我想合并所有对象并连接它们的子对象。

嵌套层级可以尽可能多,没有限制。

[
  {
    'text':'parent 1',
    'children': [
      {
        'text':'children 2',
        'children': [
          {
            'text':'parent 3',
            'children': [
              {
                'text':'parent 4',
                'children': [
                  ...
                ]
              },
            ]
          },
        ]
      }
    ]
  }
]

有可能吗?

【问题讨论】:

  • 最好的方法是创建函数,将一个元素一个一个地添加到树中,并返回每个步骤的结果树。但是在插入之前,您需要检查您在当前步骤中拥有的完整树,(开始为空),与树中存在的所有元素,父母和孩子进行比较。(可能是电阻率?)您可以从叶子开始(最后孩子)或父母,这两种方法都有自己的技巧。
  • 能否请您发布您需要的输出?
  • @Nidhin 是的,我已经添加了

标签: javascript arrays object lodash


【解决方案1】:

如果您只想合并具有相同“文本”的对象并删除重复项,使用 lodash 的一种解决方案可能是:

var d = [{
  'text': 'parent 1',
  'children': []
}, {
  'text': 'parent 2',
  'children': []
}, {
  'text': 'parent 3',
  'children': []
}, {
  'text': 'parent 1',
  'children': [{
    'text': 'children 1',
    'children': []
  }, {
    'text': 'children 2',
    'children': []
  }]
}];

var res = _.reduce(d, (memo, o) => {
  var already = _.find(memo, o1 => o.text === o1.text);
  return already ? (already.children = already.children.concat(o.children), memo) : memo.concat(o);
}, []);
console.log(res);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

虽然此解决方案不包括构建超过两个级别的树。

更新

假设您的数组的结构将代表一棵树的结构:每个“级别”代表树的一个级别,并且数组中同一级别的对象在数组中的同一级别,使用递归的可能解决方案可以是:

var tree = [{
  'text': 'A',
  'children': [{
    'text': 'A.1',
    'children': [{
      'text': 'A.1.1',
      'children': [{
        'text': 'A.1.1.1',
        'children': [{
          'text': 'A.1.1.1.1'
        }]
      }, {
        'text': 'A.1.1.1',
        'children': [{
          'text': 'A.1.1.1.2'
        }]
      }]
    }]
  }, {
    'text': 'A.2',
    'children': [{
      'text': 'A.2.1',
      'children': [{
        'text': 'A.2.1.1',
        'children': []
      }]
    }]
  }]
}, {
  'text': 'B',
  'children': []
}, {
  'text': 'C',
  'children': []
}, {
  'text': 'A',
  'children': [{
    'text': 'A.3',
    'children': []
  }, {
    'text': 'A.4',
    'children': []
  }]
}];

function joinChildren(childrenArray) {
  return _.reduce(childrenArray, function(memo, o) {
    var already = _.find(memo, function(o1) {
      return o.text === o1.text;
    });
    return already ? (already.children = already.children.concat(o.children), memo) : memo.concat(o);
  }, []);
}

function joinChildrenRecursively(rootArray) {
  rootArray = joinChildren(rootArray);
  _.forEach(rootArray, obj => {
    if (_.isArray(obj.children)) {
      obj.children = joinChildrenRecursively(obj.children);
    }
  });
  return rootArray;
}

console.log(joinChildrenRecursively(tree));
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>

希望对你有帮助。

【讨论】:

  • 谢谢,它几乎可以满足我的要求,但是子数组现在由数组而不是对象组成。是否有可能以某种方式改变它?
  • @ConstantineGolub 当然,我已经用可能的解决方案更新了答案。结果是否符合预期?谢谢!
  • 谢谢,它现在可以工作了,但似乎最大嵌套级别为 2,是否有可能以某种方式修复它?
  • @ConstantineGolub 您可能必须使用递归来构造结果。解决方案将取决于您正在使用的数据结构(节点在数组中的位置)。你能提供一个完整的例子吗?
  • 我在问题描述中添加了嵌套数据的示例
【解决方案2】:

可以通过使用新的Object.values() 和纯 JS 来执行以下操作;

var data =  [
      {
        'text':'parent 1',
        'children': [
          {
            'text':'children 3'
          }
        ]
      },
      {
        'text':'parent 2',
        'children': []
      },
      {
        'text':'parent 3',
        'children': []
      },
      {
        'text':'parent 1',
        'children': [
          {
            'text':'children 1',
            'children': []
          },
          {
            'text':'children 2',
            'children': []
          }
        ]
      }
    ],
   nested = Object.values(data.reduce((p,c) => (p[c.text] === undefined ? p[c.text] = {id: c.text, children: c.children}
                                                                        : p[c.text].children.push(...c.children),p), {}));
console.log(nested);

【讨论】:

  • 谢谢,现在它有一个所有树的根。可以省略吗?
  • @Constantine Golub 你说得对,我已经重构了我的代码。检查一下:)
猜你喜欢
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 2021-09-14
  • 2021-06-26
  • 1970-01-01
相关资源
最近更新 更多