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

JS 樹與數(shù)組相互轉(zhuǎn)換的幾種方法

 更新時間:2026年02月24日 09:43:14   作者:發(fā)現(xiàn)一只大呆瓜  
本文主要介紹了JS 樹與數(shù)組相互轉(zhuǎn)換的幾種方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

在前端業(yè)務中,后端返回的扁平化數(shù)組(Array)往往需要轉(zhuǎn)換為樹形結(jié)構(gòu)(Tree)來適配 UI 組件(如 Element UI 的 Tree 或 Cascader)。掌握多種轉(zhuǎn)換思路及性能差異,是進階高級前端的必備技能。

一、 核心概念:結(jié)構(gòu)對比

數(shù)組結(jié)構(gòu):每一項通過 parentId 指向父級。

  const nodes = [
    { id: 3, name: '節(jié)點C', parentId: 1 },
    { id: 6, name: '節(jié)點F', parentId: 3 },
    { id: 0, name: 'root', parentId: null },
    { id: 1, name: '節(jié)點A', parentId: 0 },
    { id: 8, name: '節(jié)點H', parentId: 4 },
    { id: 4, name: '節(jié)點D', parentId: 1 },
    { id: 2, name: '節(jié)點B', parentId: 0 },
    { id: 5, name: '節(jié)點E', parentId: 2 },
    { id: 7, name: '節(jié)點G', parentId: 2 },
    { id: 9, name: '節(jié)點I', parentId: 5 },
  ];

樹形結(jié)構(gòu):父級通過 children 數(shù)組包裹子級。

  let tree = [
    {
      id: 1,
      name: 'text1',
      parentId: 1,
      children: [
        {
          id: 2,
          name: 'text2',
          parentId: 1,
          children: [
            {
              id: 4,
              name: 'text4',
              parentId: 2,
            },
          ],
        },
        {
          id: 3,
          name: 'text3',
          parentId: 1,
        },
      ],
    },
  ];

二、 數(shù)組轉(zhuǎn)樹

1. 遞歸思路

原理

  1. 首先需要傳遞給函數(shù)兩個參數(shù):數(shù)組、當前的父節(jié)點id
  2. 設置一個結(jié)果數(shù)組res,遍歷數(shù)組,先找到子元素的父節(jié)點id與父節(jié)點id一致的子項
  3. 將這個子項的id作為父節(jié)點id傳入函數(shù),繼續(xù)遍歷
  4. 將遍歷的結(jié)果作為children返回,并給當前項添加children
  5. 將這個當前項,插入到res里面,并返回

注意:如果不想影響原數(shù)組,需要先深拷貝一下數(shù)組。const cloneArr = JSON.parse(JSON.stringify (arr))

  const nodes = [
    { id: 3, name: '節(jié)點C', parentId: 1 },
    { id: 6, name: '節(jié)點F', parentId: 3 },
    { id: 0, name: 'root', parentId: null },
    { id: 1, name: '節(jié)點A', parentId: 0 },
    { id: 8, name: '節(jié)點H', parentId: 4 },
    { id: 4, name: '節(jié)點D', parentId: 1 },
    { id: 2, name: '節(jié)點B', parentId: 0 },
    { id: 5, name: '節(jié)點E', parentId: 2 },
    { id: 7, name: '節(jié)點G', parentId: 2 },
    { id: 9, name: '節(jié)點I', parentId: 5 },
  ];
  //遞歸寫法
  const arrToTree1 = (arr, id) => {
    const res = [];
    arr.forEach((item) => {
      if (item.parentId === id) {
        const children = arrToTree1(arr, item.id);
        //如果希望每個元素都有children屬性,可以直接賦值
        if (children.length !== 0) {
          item.children = children;
        }
        res.push(item);
      }
    });
    return res;
  };
  console.log(arrToTree1(nodes, null));

2. 非遞歸思路

原理:利用 filter 進行二次篩選。雖然寫法簡潔,但在大數(shù)據(jù)量下性能較差(O(n2)O(n^2)O(n2))。

  1. 函數(shù)只需要接受一個參數(shù),也就是需要轉(zhuǎn)換的數(shù)組arr
  2. 第一層過濾數(shù)組,直接返回一個parentId為根id的元素
  3. 但是在返回之間,需要再根據(jù)當前id過濾里面的每一項(過濾規(guī)則為如果子項的paentId為當前的id,則在當前項的children插入這個子項)
  const arrToTree2 = (arr) => {
    return arr.filter((father) => {
      const childrenArr = arr.filter((children) => {
        return children.parentId === father.id;
      });
      //如果希望每個元素都有children屬性,可以直接賦值
      if (childrenArr.length !== 0) {
        father.children = childrenArr;
      }
      return father.parentId === null;
    });
  };
  console.log(arrToTree2(nodes));

3. Map 對象方案(O(n)O(n)O(n)時間復雜度)

原理:利用對象的引用性質(zhì)。先將數(shù)組轉(zhuǎn)為 Map,再遍歷一次即可完成。這是在大數(shù)據(jù)量下的首選方案。

  const arrToTree3 = (arr) => {
    const map = {};
    const res = [];

    // 1. 建立映射表
    arr.forEach((item) => {
      map[item.id] = { ...item, children: [] };
    });

    // 2. 組裝樹結(jié)構(gòu)
    arr.forEach((item) => {
      const node = map[item.id];
      if (item.parentId === null) {
        res.push(node);
      } else {
        if (map[item.parentId]) {
          map[item.parentId].children.push(node);
        }
      }
    });
    return res;
  };
  console.log(arrToTree3(nodes));

三、 樹轉(zhuǎn)數(shù)組

1. 遞歸遍歷思路

原理:定義一個結(jié)果數(shù)組,遞歸遍歷樹的每一層,將節(jié)點信息(排除 children)推入數(shù)組。

  1. 首先定義一個結(jié)果數(shù)組res,遍歷傳入的樹
  2. 直接將當前項的id、name、parentId包裝在一個新對象里插入
  3. 判斷是否有children屬性,如果有則遍歷children屬性每一項,繼續(xù)執(zhí)行2、3步驟
  let tree = [
    {
      id: 1,
      name: 'text1',
      parentId: 1,
      children: [
        {
          id: 2,
          name: 'text2',
          parentId: 1,
          children: [
            {
              id: 4,
              name: 'text4',
              parentId: 2,
            },
          ],
        },
        {
          id: 3,
          name: 'text3',
          parentId: 1,
        },
      ],
    },
  ];
  const treeToArr = (tree) => {
    const res = [];
    tree.forEach((item) => {
      const loop = (data) => {
        res.push({
          id: data.id,
          name: data.name,
          parseId: data.parentId,
        });
        if (data.children) {
          data.children.forEach((itemChild) => {
            loop(itemChild);
          });
        }
      };
      loop(item);
    });
    return res;
  };
  console.log(treeToArr(tree));

四、 注意事項:深拷貝的必要性

在處理這些轉(zhuǎn)換時,由于 JS 的對象是引用類型,直接修改 item.children 會改變原始數(shù)組的內(nèi)容。

  • 快捷方案:const cloneArr = JSON.parse(JSON.stringify(arr))。
  • 避坑點:如果數(shù)組項中包含 Date 對象、RegExp 或 Function,JSON.parse 會導致數(shù)據(jù)失真,此時應使用其他深拷貝方案。

到此這篇關(guān)于JS 樹與數(shù)組相互轉(zhuǎn)換的幾種方法的文章就介紹到這了,更多相關(guān)JS 樹與數(shù)組相互轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • 詳解JavaScript如何實現(xiàn)一個簡易的Promise對象

    詳解JavaScript如何實現(xiàn)一個簡易的Promise對象

    Promise對象的作用將異步操作以同步操作的流程表達出來,避免層層嵌套的回調(diào)函數(shù),而且Promise提供了統(tǒng)一的接口,使得控制異步操作更加容易。本文介紹了如何實現(xiàn)一個簡單的Promise對象,需要的可以參考一下
    2022-11-11
  • Bootstrap 附加導航(Affix)插件實例詳解

    Bootstrap 附加導航(Affix)插件實例詳解

    附加導航(Affix)插件允許某個 <div> 固定在頁面的某個位置。接下來通過本文給大家介紹Bootstrap 附加導航(Affix)插件實例詳解,感興趣的朋友一起看看吧
    2016-06-06
  • 如何解決IONIC頁面底部被遮住無法向上滾動問題

    如何解決IONIC頁面底部被遮住無法向上滾動問題

    Ionic 是目前最有潛力的一款 HTML5 手機應用開發(fā)框架。在開發(fā)過程中我們同樣會遇到各種各樣奇葩的問題。下面小編給大家?guī)砹擞嘘P(guān)IONIC頁面底部被遮住無法向上滾動問題的解決方案
    2016-09-09
  • 一文詳解JSON.parse和JSON.stringify的用法

    一文詳解JSON.parse和JSON.stringify的用法

    Json.stringify()和toString()兩者雖然都可以講目標值轉(zhuǎn)為字符串,但是還是有本質(zhì)區(qū)別的,下面這篇文章主要給大家介紹了關(guān)于JSON.parse和JSON.stringify用法的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • 淺談JS中this在各個場景下的指向

    淺談JS中this在各個場景下的指向

    這篇文章主要介紹了淺談JS中this在各個場景下的指向,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-08-08
  • IE下通過a實現(xiàn)location.href 獲取referer的值

    IE下通過a實現(xiàn)location.href 獲取referer的值

    IE下采用window.location.href方式跳轉(zhuǎn)的話,referer值為空在標簽a里面的跳轉(zhuǎn)的話referer就不會空,下面是具體的實現(xiàn)代碼
    2014-09-09
  • javaScript中的空值和假值

    javaScript中的空值和假值

    JavaScript 是世界上最流行的編程語言。javaScript中有五種空值和假值,分別為false,null,undefined,“”,0。從廣義上來說,這五個值都是對應數(shù)據(jù)類型的無效值或空值
    2017-12-12
  • uniapp開發(fā)小程序?qū)崿F(xiàn)全局懸浮按鈕的代碼

    uniapp開發(fā)小程序?qū)崿F(xiàn)全局懸浮按鈕的代碼

    這篇文章主要介紹了uniapp開發(fā)小程序如何實現(xiàn)全局懸浮按鈕,但是在uniapp中式?jīng)]有window對象,和dom元素的,需要獲取頁面上節(jié)點的幾何信息,具體實例代碼詳細跟隨小編一起看看吧
    2022-03-03
  • javascript 封裝Date日期類實例詳解

    javascript 封裝Date日期類實例詳解

    這篇文章主要介紹了javascript-封裝Date日期類的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • layui使用label標簽的方法

    layui使用label標簽的方法

    今天小編就為大家分享一篇layui使用label標簽的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09

最新評論

五大连池市| 翁牛特旗| 兴文县| 米泉市| 徐汇区| 桐城市| 洛阳市| 伊宁县| 神农架林区| 永寿县| 吉安县| 西安市| 宾阳县| 广西| 攀枝花市| 德阳市| 阿克陶县| 长顺县| 历史| 巴马| 兴和县| 通城县| 濉溪县| 桃江县| 灌阳县| 武鸣县| 汾阳市| 利津县| 龙江县| 涿鹿县| 汉中市| 从化市| 湖北省| 峡江县| 广平县| 綦江县| 六安市| 遵化市| 会泽县| 当涂县| 庄浪县|