最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript樹形數(shù)據(jù)扁平化的三種實(shí)現(xiàn)方法(遞歸/迭代/flatMap)

 更新時(shí)間:2025年08月18日 09:57:31   作者:編程隨想_Code  
樹形數(shù)據(jù)結(jié)構(gòu)在前端應(yīng)用中被廣泛用于表示層級(jí)關(guān)系的數(shù)據(jù),如菜單、部門結(jié)構(gòu)、文件目錄等,扁平化操作通常是指將具有層級(jí)關(guān)系的樹形數(shù)據(jù)轉(zhuǎn)換為單一維度的數(shù)據(jù)結(jié)構(gòu),即數(shù)組,本文給大家介紹了JavaScript樹形數(shù)據(jù)扁平化的三種實(shí)現(xiàn)方法,需要的朋友可以參考下

在前端開發(fā)中,我們經(jīng)常會(huì)遇到 樹形結(jié)構(gòu)(Tree Data Structure) 的數(shù)據(jù),比如:

  • 菜單列表(菜單 → 子菜單 → 孫菜單)
  • 部門組織架構(gòu)(公司 → 部門 → 小組 → 員工)
  • 樹狀分類(分類 → 子分類 → 子子分類)

而有時(shí)候,我們需要將樹形數(shù)據(jù)拍平成一維數(shù)組,方便做搜索、統(tǒng)計(jì)、映射等操作。

一、樹形結(jié)構(gòu)的特點(diǎn)

一個(gè)典型的樹形結(jié)構(gòu)數(shù)據(jù)可能是這樣的:

const treeData = [
  {
    id: 1,
    name: "A",
    children: [
      {
        id: 2,
        name: "A-1",
        children: [
          { id: 3, name: "A-1-1" },
          { id: 4, name: "A-1-2" }
        ]
      },
      {
        id: 5,
        name: "A-2"
      }
    ]
  },
  {
    id: 6,
    name: "B"
  }
];

特點(diǎn):

  1. 每個(gè)節(jié)點(diǎn)可能有 children 屬性存放子節(jié)點(diǎn)。
  2. 層級(jí)關(guān)系不固定,可能有很多層。
  3. 數(shù)據(jù)訪問需要遞歸或迭代遍歷。

二、為什么要轉(zhuǎn)換成普通數(shù)組?

樹形結(jié)構(gòu)雖然表達(dá)了層級(jí)關(guān)系,但在以下場(chǎng)景下并不方便:

  • 全局搜索:需要遍歷所有節(jié)點(diǎn)匹配關(guān)鍵字。
  • 批量操作:需要一次性拿到所有節(jié)點(diǎn)的 ID 或名稱。
  • 統(tǒng)計(jì):統(tǒng)計(jì)節(jié)點(diǎn)數(shù)量、節(jié)點(diǎn)類型等。

將樹形數(shù)據(jù)拍平成數(shù)組后,數(shù)據(jù)會(huì)變成這樣:

[
  { id: 1, name: "A" },
  { id: 2, name: "A-1" },
  { id: 3, name: "A-1-1" },
  { id: 4, name: "A-1-2" },
  { id: 5, name: "A-2" },
  { id: 6, name: "B" }
]

這樣處理起來就非常方便。

三、實(shí)現(xiàn)方法

方法一:遞歸實(shí)現(xiàn)

遞歸是處理樹形結(jié)構(gòu)的經(jīng)典方式。

function treeToArray(tree) {
  let result = [];

  function traverse(nodeList) {
    for (const node of nodeList) {
      // 拷貝當(dāng)前節(jié)點(diǎn)(防止修改原數(shù)據(jù))
      const { children, ...rest } = node;
      result.push(rest);

      // 如果有子節(jié)點(diǎn),遞歸處理
      if (children && children.length) {
        traverse(children);
      }
    }
  }

  traverse(tree);
  return result;
}

const flatArray = treeToArray(treeData);
console.log(flatArray);

運(yùn)行結(jié)果:

[
  { id: 1, name: 'A' },
  { id: 2, name: 'A-1' },
  { id: 3, name: 'A-1-1' },
  { id: 4, name: 'A-1-2' },
  { id: 5, name: 'A-2' },
  { id: 6, name: 'B' }
]

方法二:迭代(棧)實(shí)現(xiàn)

如果不想用遞歸,可以用棧來實(shí)現(xiàn)。

function treeToArrayIterative(tree) {
  let result = [];
  let stack = [...tree]; // 先把根節(jié)點(diǎn)放進(jìn)棧

  while (stack.length) {
    const node = stack.pop();
    const { children, ...rest } = node;
    result.push(rest);

    // 注意:這里用棧,所以先放子節(jié)點(diǎn)才能保證順序
    if (children && children.length) {
      stack.push(...children);
    }
  }

  return result;
}

const flatArray2 = treeToArrayIterative(treeData);
console.log(flatArray2);

方法三:使用 Array.flatMap(ES2019+)

如果層級(jí)不深,可以用 flatMap + 遞歸的方式更簡(jiǎn)潔:

function treeToArrayFlatMap(tree) {
  return tree.flatMap(({ children, ...rest }) =>
    children ? [rest, ...treeToArrayFlatMap(children)] : [rest]
  );
}

console.log(treeToArrayFlatMap(treeData));

四、性能對(duì)比

  • 遞歸:代碼簡(jiǎn)潔、可讀性好,適合絕大多數(shù)場(chǎng)景。
  • 迭代:避免遞歸棧溢出,適合極深層級(jí)的樹。
  • flatMap:語法簡(jiǎn)潔,但瀏覽器兼容性略差(需 ES2019+)。

五、總結(jié)

樹形結(jié)構(gòu)轉(zhuǎn)換為普通數(shù)組的關(guān)鍵點(diǎn)在于:

  1. 遍歷:無論遞歸還是迭代,都需要訪問每一個(gè)節(jié)點(diǎn)。
  2. 數(shù)據(jù)處理:在 push 到結(jié)果數(shù)組時(shí),去掉 children,避免冗余。
  3. 順序:遞歸天然保證順序,迭代需要注意入棧順序。

在實(shí)際項(xiàng)目中,可以根據(jù)數(shù)據(jù)規(guī)模和瀏覽器兼容性選擇合適的方式。

建議

在處理樹形結(jié)構(gòu)時(shí),可以先封裝一個(gè)通用的遍歷方法,這樣后續(xù)不僅能拍平數(shù)組,還可以做任意數(shù)據(jù)加工,比如篩選、映射等。

到此這篇關(guān)于JavaScript樹形數(shù)據(jù)扁平化的三種實(shí)現(xiàn)方法(遞歸/迭代/flatMap)的文章就介紹到這了,更多相關(guān)JavaScript樹形數(shù)據(jù)扁平化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript forEach方法用法示例實(shí)戰(zhàn)

    JavaScript forEach方法用法示例實(shí)戰(zhàn)

    本文將詳細(xì)介紹forEach方法的基本概念、用法、常見的應(yīng)用場(chǎng)景、與其他遍歷方法的對(duì)比,并提供實(shí)戰(zhàn)示例,幫助您全面掌握這一強(qiáng)大的工具,感興趣的朋友跟隨小編一起看看吧
    2025-06-06
  • JavaScript中不可忽略的Symbol的盤點(diǎn)

    JavaScript中不可忽略的Symbol的盤點(diǎn)

    Symbol類型的出現(xiàn),為每個(gè)屬性賦予了獨(dú)一無二的標(biāo)識(shí)符,無論項(xiàng)目多么復(fù)雜,Symbol都能確保屬性鍵的絕對(duì)唯一性,下面我們就來看看JavaScript中那些不可忽略的Symbol吧
    2024-12-12
  • JavaScript中的scrollTop詳解(滾動(dòng)到頂部)

    JavaScript中的scrollTop詳解(滾動(dòng)到頂部)

    scrollTop是JavaScript中一個(gè)非常有用且重要的方法,它用于獲取或設(shè)置元素的垂直滾動(dòng)條位置,這篇文章主要給大家介紹了關(guān)于JavaScript中scrollTop詳解(滾動(dòng)到頂部)的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • JavaScript封裝LINQ查詢方法實(shí)戰(zhàn)

    JavaScript封裝LINQ查詢方法實(shí)戰(zhàn)

    本文主要介紹了通過js-linq庫(kù)在JavaScript中實(shí)現(xiàn)類似.NET LINQ的查詢功能,封裝Where、Select、OrderBy等方法,提升數(shù)組和可迭代對(duì)象的數(shù)據(jù)處理效率與代碼可讀性
    2025-09-09
  • javascript設(shè)計(jì)模式--策略模式之輸入驗(yàn)證

    javascript設(shè)計(jì)模式--策略模式之輸入驗(yàn)證

    策略模式中的策略就是一種算法或者業(yè)務(wù)規(guī)則,將這些策略作為函數(shù)進(jìn)行封裝,并向外提供統(tǒng)一的調(diào)用執(zhí)行,本文給大家介紹javascript設(shè)計(jì)模式--策略模式之輸入驗(yàn)證,需要的朋友參考下
    2015-11-11
  • JavaScript仿聊天室聊天記錄

    JavaScript仿聊天室聊天記錄

    這篇文章主要為大家詳細(xì)介紹了JavaScript仿聊天室聊天記錄實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 微信小程序之?dāng)?shù)據(jù)緩存的實(shí)例詳解

    微信小程序之?dāng)?shù)據(jù)緩存的實(shí)例詳解

    這篇文章主要介紹了微信小程序之?dāng)?shù)據(jù)緩存的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • JavaScript實(shí)現(xiàn)清除首尾空白字符再進(jìn)行空白匹配

    JavaScript實(shí)現(xiàn)清除首尾空白字符再進(jìn)行空白匹配

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)清除首尾空白字符再進(jìn)行空白匹配的相關(guān)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2025-12-12
  • 詳解bootstrap導(dǎo)航欄.nav與.navbar區(qū)別

    詳解bootstrap導(dǎo)航欄.nav與.navbar區(qū)別

    本篇文章主要介紹了詳解bootstrap導(dǎo)航欄.nav與.navbar區(qū)別,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • js使用setTimeout實(shí)現(xiàn)定時(shí)炸彈的方法

    js使用setTimeout實(shí)現(xiàn)定時(shí)炸彈的方法

    這篇文章主要介紹了js使用setTimeout實(shí)現(xiàn)定時(shí)炸彈的方法,涉及javascript中setTimeout方法的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-04-04

最新評(píng)論

长白| 武冈市| 婺源县| 连州市| 杭锦旗| 突泉县| 宁夏| SHOW| 南昌市| 宜丰县| 哈尔滨市| 凤冈县| 镶黄旗| 镇康县| 宁城县| 龙海市| 迁西县| 太白县| 贵阳市| 大余县| 海原县| 大荔县| 贵溪市| 镇宁| 本溪| 杂多县| 白水县| 安泽县| 宁远县| 塔河县| 义马市| 太湖县| 双峰县| 岳西县| 江北区| 威海市| 张家界市| 页游| 晋江市| 宁强县| 曲阜市|