【问题标题】:Traverse a tree like array遍历树状数组
【发布时间】:2019-02-25 12:31:27
【问题描述】:

我有一个看起来像树结构的数组。它是对象数组,其中对象有一个子数组,而子对象还有一个子数组。下面是示例。我曾尝试在问题中使用递归,但无法获得所需的结果。

[
    {
      parentId: null,
      children: [
        {
          parentId: 267,
          children: [
            {
              parentId: 268,
              children: [
                {
                  parentId: 270,
                  children: null,
                }
              ],
            },
            {
              parentId: 268,
              children: [
                {
                  parentId: 269,
                  children: null,
                }
              ],
            }
          ],
        }
      ],
    },
   ...
   ...
  ];

我想遍历这个数组并在每个对象中添加一个键和一个值。

例如 open : 'fa fa-open'

结果数组中的每个对象都必须具有上述键。

【问题讨论】:

  • 您是要获取一个新数组还是只是将属性插入现有数组和子数组中?
  • 进入现有阵列。我也无法复制这个数组,因为弹出了一些循环 json 错误

标签: javascript arrays recursion tree


【解决方案1】:

请看下面链接中的代码,它递归遍历所有子节点并插入 open: 'fa fa-open' https://codesandbox.io/s/o4jvxloy7q

【讨论】:

  • 如果给定了 parentid,我是否可以将图标仅添加到特定父级及其子级
  • @RenilBabu 是的,您可以将 parentId 作为参数传递给函数,并且添加打开密钥的位置使其成为条件。
  • 但我认为这只是一个级别。我需要给定 parentid 的所有孩子和进一步的孩子不要有 fa fa-open
【解决方案2】:

这类问题非常适合学习相互递归。

首先,我们使用高阶函数f 对traverse 和单个node 及其children 进行某种处理——

const traverse = (f, { children = [], ...node }) =>
  f ({ ...node, children: children.map (c => traverse (f, c)) })

例如,将属性hello设置为'world'添加到每个节点-

traverse
  ( node => ({ ...node, hello: 'world' })
  , { a: 1, children: [ { b: 2 } ] }
  )

// { a: 1
// , children:
//     [ { b: 2
//       , children: []
//       , hello: 'world'
//       }
//     ]
//  }

但这仅适用于 单个 节点。你有一个 array 节点,所以 -

const traverseAll = (f, nodes = []) =>
  nodes.map (node => traverse (f, node))

当您回顾traverse 时,我们看到我们重复了自己(bold)–

const traverse = (f, { children = [], ...node }) =>
  f ({ ...node, children: children.map (c => traverse (f, c)) })

const traverseAll = (f, nodes = []) =>
  nodes.map (node => traverse (f, node))

使用相互递归定义,我们写出和谐对——

const traverseAll = (f, nodes = []) =>
  nodes.map (node => traverse (f, node))

const traverse = (f, { children = [], ...node }) =>
  f ({ ...node, children: traverseAll (f, children) })

在下面的浏览器中验证完整的程序-

const traverseAll = (f, nodes = []) =>
  nodes.map (node => traverse (f, node))

const traverse = (f, { children = [], ...node }) =>
  f ({ ...node, children: traverseAll (f, children) })

const nodes =
  [ { id: 1
    , children:
        [ { id: 2
          , children: []
          }
        , { id: 3
          , children:
              [ { id: 4
                , children: []
                }
              ]
          }
        ]
     }
   , { id: 5
     , children: []
     }
   ]
   
console.log
  ( traverseAll
      ( node => ({ ...node, open: 'fa fa-open' })
      , nodes
      )
  )

// [ { id: 1
//   , children: 
//       [ { id: 2, children: [], open: 'fa fa-open' },
//         { id: 3
//         , children:
//             [ { id: 4
//               , children: []
//               , open: 'fa fa-open'
//               }
//             ]
//         , open: 'fa fa-open'
//         }
//       ]
//   , open: 'fa fa-open'
//   }
// , { id: 5
//   , children: []
//   , open: 'fa fa-open'
//   }
// ]

【讨论】:

    【解决方案3】:

    let data = [
      {
        parentId: 123,
        children: [],
      },
      {
        parentId: 345,
        children: [],
      },
      {
        parentId: 1567,
        children: [],
      },
    ];
    
    data.forEach(item => item.open = "new value")
    console.log(data)

    【讨论】:

    • 此代码只能用于平面数组。问题是关于嵌套的。例如,孩子们会像树状结构一样拥有孩子。
    • 我误解了这个问题。
    【解决方案4】:

    您可以使用forEach 循环创建递归函数,该循环获取数据和一个对象并将该对象分配给数据中的每个对象。

    const data = [{"parentId":null,"children":[{"parentId":267,"children":[{"parentId":268,"children":[{"parentId":270,"children":null}]},{"parentId":268,"children":[{"parentId":269,"children":null}]}]}]}]
    
    function add(data, obj) {
      data.forEach(e => {
        Object.assign(e, obj);
        if (e.children) add(e.children, obj)
      })
    }
    
    add(data, {open: 'fa fa-open'})
    console.log(data)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多