【问题标题】:How to reduce an array with the depth of a particular property如何减少具有特定属性深度的数组
【发布时间】:2021-03-27 17:07:24
【问题描述】:

输入

下面是我要减少的对象

  data = [
    {
      id: "m1",
      name: "menu1",
      val: "D",
      items: [
        {
          id: "d1",
          name: "datanested1",
          val: "D",
          items: [
            { id: "1", name: "direct Data", val: "E" },
            { id: "2", name: "test", val: "E" }
          ]
        }
      ]
    },
    {
      id: "d2",
      name: "menu2",
      val: "D",
      items: [
        { id: "21", name: "test21", val: "E" },
        { id: "22", name: "test23", val: "E" }
      ]
    },
    {
      id: "d3",
      name: "menu3",
      val: "D",
      items: [
        { id: "31", name: "test data 3", val: "E" },
        { id: "32", name: "test data 4", val: "E" }
      ]
    }
  ];

输出

我的期望是对象减少到下面

[
  {
    "id": "m1",
    "name": "menu1",
    "val": "D",
    "depth": 2
  },
  {
    "id": "d1",
    "name": "datanested1",
    "val": "D",
    "parentId": "m1",
    "depth": 1
  },
  {
    "id": "1",
    "name": "direct Data",
    "val": "E",
    "parentId": "d1",
    "depth": 0
  },
  {
    "id": "2",
    "name": "test",
    "val": "E",
    "parentId": "d1",
    "depth": 0
  },
  {
    "id": "d2",
    "name": "menu2",
    "val": "D",
    "depth": 1
  },
  {
    "id": "22",
    "name": "test23",
    "val": "E",
    "parentId": "d2",
    "depth": 0
  },
  {
    "id": "21",
    "name": "test21",
    "val": "E",
    "parentId": "d2",
    "depth": 0
  },
  {
    "id": "d3",
    "name": "menu3",
    "val": "D",
    "depth": 1
  },
  {
    "id": "32",
    "name": "test data 4",
    "val": "E",
    "parentId": "d3",
    "depth": 0
  },
  {
    "id": "31",
    "name": "test data 3",
    "val": "E",
    "parentId": "d3",
    "depth": 0
  }

]

说明

depth 是属性.items 的层数,例如

id: "1" 的属性有 0 个子代为属性items,其深度值为0
id: "2" 的属性有 0 个子代为属性 items,其深度值为 0
具有 id: "d1" 的属性有1 个子代属性items,其深度值为1
id: "m1" 的属性有 2 个子代属性 items,其深度值为 2
...

我目前的方法

以下是我目前拥有的

function reducedArray(myArray) {
    let newReduced = myArray;
    let noMoreItems = false;
    while (!noMoreItems) {
      newReduced = newReduced.reduce((prev, next) => {
        const parent = { ...next };
        delete parent.items;
        if (!parent.depth) {
          parent.depth = 0;
        } else {
          parent.depth = parent.depth + 1;
        }
        if (!next.items) {
          return [parent, ...prev];
        }
        return [
          parent,
          ...prev,
          ...next.items.map(item => ({
            ...item,
            parentId: next.id
          }))
        ];
      }, []);

      noMoreItems = true;
      noMoreItems = !newReduced.find(({ items }) => items);
    }
    return newReduced;
  }
  
  const myArray = [{"id":"m1","name":"menu1","val":"D","items":[{"id":"d1","name":"datanested1","val":"D","items":[{"id":"1","name":"direct Data","val":"E"},{"id":"2","name":"test","val":"E"}]}]},{"id":"d2","name":"menu2","val":"D","items":[{"id":"21","name":"test21","val":"E"},{"id":"22","name":"test23","val":"E"}]},{"id":"d3","name":"menu3","val":"D","items":[{"id":"31","name":"test data 3","val":"E"},{"id":"32","name":"test data 4","val":"E"}]}];
  
  console.log(reducedArray(myArray))

挑战

该方法似乎按预期减少了数组,挑战在于没有保持深度,加上顺序不符合预期。顺序很重要,因为它用于在表单中生成 UI

  menu1
      datanested1
         direct Data
         test

depth 属性将用于格式化缩进

请协助调试或建议我如何转换此数据

【问题讨论】:

  • 你试过递归吗?

标签: javascript arrays algorithm


【解决方案1】:

简单的递归方法。深度“倒退”于您的预期,但之后更容易修复(或按原样使用)。

function handleArray(arr, depth, parentId) {
  return arr.reduce((acc, el) => {
    const {items, ...otherProps} = el;
    acc.push({...otherProps, parentId, depth});
    if (items) {
      return acc.concat(handleArray(items, depth + 1, el.id));
    }
    return acc;
  }, []);
}
  
  const myArray = [{"id":"m1","name":"menu1","val":"D","items":[{"id":"d1","name":"datanested1","val":"D","items":[{"id":"1","name":"direct Data","val":"E"},{"id":"2","name":"test","val":"E"}]}]},{"id":"d2","name":"menu2","val":"D","items":[{"id":"21","name":"test21","val":"E"},{"id":"22","name":"test23","val":"E"}]},{"id":"d3","name":"menu3","val":"D","items":[{"id":"31","name":"test data 3","val":"E"},{"id":"32","name":"test data 4","val":"E"}]}];
  
console.log(handleArray(myArray, 0, ""));

【讨论】:

  • 这看起来很有希望,让我看看我现在的情况是否可以实现它
【解决方案2】:

您可以对reduce 使用递归方法,但您还需要单独的递归调用来获取深度,以便您可以获得所需的元素顺序和正确的深度结果。

const data = [{"id":"m1","name":"menu1","val":"D","items":[{"id":"d1","name":"datanested1","val":"D","items":[{"id":"1","name":"direct Data","val":"E"},{"id":"2","name":"test","val":"E"}]}]},{"id":"d2","name":"menu2","val":"D","items":[{"id":"21","name":"test21","val":"E"},{"id":"22","name":"test23","val":"E"}]},{"id":"d3","name":"menu3","val":"D","items":[{"id":"31","name":"test data 3","val":"E"},{"id":"32","name":"test data 4","val":"E"}]}]

function fDepth(data, lvl = 1) {
    return data.reduce((r, { items }) => {
        return items ? fDepth(items, lvl + 1) : lvl;
    }, lvl);
}

function f(data, parentId = null) {
    return data.reduce((r, { id, name, val, items }) => {
        const obj = { id, name, val };

        if (parentId) obj.parentId = parentId;
        obj.depth = items ? fDepth(items) : 0;

        r.push(obj);

        if (items) r.push(...f(items, id));

        return r;
    }, []);
}

const result = f(data);
console.log(result);

【讨论】:

  • 感谢您的回答,确实符合我的要求
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
相关资源
最近更新 更多