主頁 > .NET開發 > Typescript平面物件到嵌套樹物件,如何用不同的值構建它?

Typescript平面物件到嵌套樹物件,如何用不同的值構建它?

2022-11-21 14:09:35 .NET開發

這是我正在處理的平面物件,它有更多的結果,~6800。我一直在嘗試將它轉換為嵌套樹(如下面所列的樹)大約 13 個小時,我真的迷路了。

[
  {
    "make": "Acura",
    "classification": "Mid SUV",
    "segment": "Competitive Trucks",
    "model": "RDX",
    "catalogDetail": "RDX_SUV_4_Gasoline_2013_Base w/Tech_FWD_3.5_6_105.7_Automatic"
  },
  {
    "make": "Acura",
    "classification": "Midsize Car",
    "segment": "Competitive Cars",
    "model": "TSX",
    "catalogDetail": "TSX_Sedan_4_Gasoline_2012_Base w/Tech_FWD_2.4_4_106.4_Automatic"
  },
  {
    "make": "Aston Martin",
    "classification": "Compact Car",
    "segment": "Competitive Cars",
    "model": "DB11",
    "catalogDetail": "DB11_Convertible_2_Gasoline_2019_Volante_RWD_4.0_8_110.4_Automatic"
  }
]

我想要做的是將這個平面物件構建成這樣的嵌套結構:

[
  {
    "make": [ 
      { "Acura",
        "classification": [{
          "Mid SUV",
          "segment": [{
            "Competitive Trucks",
            "model": [{
              "RDX",
              "catalogDetail": [{
                "RDX_SUV_4_Gasoline_2013_Base w/Tech_FWD_3.5_6_105.7_Automatic"
              }]
            }]
          }],
          "Midsize Car",      
          "segment": [{
            "Competitive Cars",
            "model": [{
              "TSX",
              "catalogDetail": [{
                "TSX_Sedan_4_Gasoline_2012_Base w/Tech_FWD_2.4_4_106.4_Automatic"
              }]
            }]
          }] 
        }],
      }
    ]
  },
  {
    "make": [
      { "Aston Martin",
        "classification": [{
          "Compact Car",
          "segment": [{
            "Competitive Cars",
            "model": [{
              "DB11",
              "catalogDetail": [{
                "DB11_Convertible_2_Gasoline_2019_Volante_RWD_4.0_8_110.4_Automatic"
              }]
            }]
          }]
        }]
      }
    ]
  }
]

其中結構屬于嵌套結構,如:制作 --> 分類 --> 細分 --> 模型 --> 目錄細節。所以會有多個汽車品牌,福特、凱迪拉克等。多個分類,每個品牌下有多個不同的細分市場。

這是我試過的:

    this._servicesService.getHierarchy().subscribe(data => {
      console.log(data)
/*      this.data = data;*/
      /*      this.dataStore = data;*/


      let distinctSeg = [...new Set(data.map(x => x.segment))];
      let distinctClass = [...new Set(data.map(x => x.classification))];
      let distinctMod = [...new Set(data.map(x => x.model))];
      let distinctCd = [...new Set(data.map(x => x.catalogDetail))];

     const newData = [];
      data.forEach(e => {
        if (newData.length == 0) {
          newData.push({
            make: e.make,
            segment: e.segment,
            classification: e.classification,
            model: [e.model],
            catalogDetail: [e.catalogDetail]
          });
        } else {
          let foundIndex = newData.findIndex(fi => fi.make === e.make, fi => fi.segment = e.segment);
          if (foundIndex >= 0) {
            /* newData[foundIndex].make.push(e.make),*/
            /* newData[foundIndex].segment.push(e.segment),*/
            /* newData[foundIndex].classification.push(e.classification),*/
            newData[foundIndex].model.push(e.model);
            newData[foundIndex].catalogDetail.push(e.catalogDetail);
          } else {
            newData.push({
              make: e.make,
              segment: distinctSeg,
              classification: distinctClass,
              model: [e.model],
              catalogDetail: [e.catalogDetail]
            });
          }
        }
      });
      console.log(newData);
    })

這為模型、段和類提供了不同的值(由于某種原因不是模型或目錄詳細資訊),但嵌套結構不存在,我真的不知道如何進行。我在這里查看了很多示例,但我確實沒有成功應用之前列出的任何路線。任何見解或提示將不勝感激。我附上了一張圖片以更好地可視化最終所需的輸出,以防我的語法錯誤。

uj5u.com熱心網友回復:

我建議您為此使用Array.reduce方法。

這個方法可以讓你輕松地將一個js陣列轉換為一個物件。

您可以執行以下操作:

arr.reduce((accumulator, currentValue)=>{
  if(!accumulator[currentValue.make]){
    accumulator[currentValue.make] = []
  }
  accumulator[currentValue.make][0] = {...<PUT YOUR OBJECT VALUE HERE>}
},{})

uj5u.com熱心網友回復:

正如 Avrham 所說,您可以使用 reduce。想象一下你創建了一個函式

  reduce(data:any[],key:string,keyArray:string)
  {
    return data.reduce((a:any[],b:any)=>{
       const element=a.find(x=>x[key]==b[key])
       const value=b[key]
       delete b[key]
       if (!element)
          a.push({[key]:value,[keyArray]:[b]})
       else
          element[keyArray].push(b)
        return a;
    },[])
  }
}

您可以使用以下方式:

 const data=this.reduce(this.data,"make","classification")
 data.forEach(x=>{
   x.classification=this.reduce(x.classification,"classification","segment")
   x.classification.forEach(c=>{
    c.segment=this.reduce(c.segment,"segment","model")
    c.segment.forEach(m=>{
       m.model=this.reduce(m.model,"model","catalogDetail")
       m.model.forEach(d=>d.catalogDetail=d.catalogDetail.map(e=>e.catalogDetail))
    })
   })
 })
 this.dataFormatted=data

但我認為管理這種樹視圖并不容易。一般來說,你有一個樹視圖,所有的陣列都是“孩子”。所以我建議創建一個函式

  reduceChildren(data:any[],key:string)
  {
    return data.reduce((a:any[],b:any)=>{
      const element=a.find(x=>x[key]==b[key])
      const value=b[key]
      delete b[key]
      if (!element)
         a.push({[key]:value,children:[b]})
      else
         element.children.push(b)
       return a;
   },[])
  }

你可以使用像

 const data=this.reduceChildren(this.data,"make")
 data.forEach(x=>{
   x.children=this.reduceChildren(x.children,"classification")
   x.children.forEach(c=>{
    c.children=this.reduceChildren(c.children,"segment")
    c.children.forEach(m=>{
       m.children=this.reduceChildren(m.children,"model")
       m.children.forEach(d=>d.children=d.children.map(e=>e.catalogDetail))
    })
   })
 })
 this.dataFormatted=data

您可以在這個 stackblitz中看到這兩種方法

uj5u.com熱心網友回復:

看起來,對于輸入輸出,你想要這樣的東西:

const inp = [
  { a: "x", b: "u", c: "q" }, { a: "x", b: "v", c: "r" },
  { a: "x", b: "u", c: "s" }, { a: "x", b: "v", c: "t" },
  { a: "y", b: "u", c: "q" }, { a: "y", b: "u", c: "r" },
  { a: "y", b: "v", c: "s" },
];

const outp = collect(inp, "a", "b", "c");
console.log(outp);
// {x:{u: ["q","s"], v:["r","t"]}, y:{u:["q","r"], v:["s"]}}

其中collect()是一個函式,它接受一個物件陣列和這些物件的鍵串列。(它至少需要一個鍵,輸入物件應該string在這些鍵上有值。)我們的作業是實作collect().


我采用的方法是遞回的;首先,基本情況,您collect(inp, key1)只需要一把鑰匙。在這種情況下,我們只想回傳key1鍵值的陣列,我們可以通過mapping輸入陣列來獲得它;inp.map(v => v[key1])

然后是遞回步驟:當你collect(inp, key1, ...keyRest)用多個鍵呼叫時,輸出將有與key1的元素的屬性對應的鍵inp在上面的示例中,如果我們呼叫collect(inp, "a", ...keyRest),則輸出將包含鍵xy對于key,我們將屬性為x的元素收集到另一個陣列中,然后key處的值為和鑰匙類似。也就是說,我們將輸入陣列拆分為對應于鍵值的子陣列,然后對每個子陣列進行評估。inpa"x"inpXxcollect(inpX, ...keyRest)ykey1collect(subArr, ...keyRest)


這是演算法的口頭描述。讓我們看看它對 for 的型別意味著什么collect()

declare function collect<K extends (keyof T)[], T extends object>(
  arr: (T & Record<K[number], string>)[], ...keys: K): Collect<K>;

type Collect<K extends PropertyKey[]> =
  K extends [any] ? string[] :
  K extends [any, ...infer R extends PropertyKey[]] ? { [k: string]: Collect<R> } :
  never;

這里我們說這collect()是一個通用函式,它接受物件型別的元素陣列和元組型別T的鍵串列我們進行約束,以便陣列的每個元素都是型別的,并且在元組中的每個鍵元素處都有一個屬性我們進行約束,使每個關鍵元素都是 的某個關鍵 K arrarrTstringKKT

我們回傳一個 type 的值Collect<K>,其中Collect<K>本身是一個遞回條件型別,表示具有嵌套string 索引簽名且其基本情況值型別為的物件string[]


現在開始實施:

function collect(arr: any[], ...keys: string[]) {
  if (!keys.length) throw new Error("need at least one key");
  const [k, ...rest] = keys;

  // base case
  if (!rest.length) return arr.map(v => v[k]);

  // recurse; first collect the sub-arrays for each value at key k
  const subArrays: Record<string, any[]> = {}
  arr.forEach(v => (subArrays[v[k]] ??= []).push(v));

  // then build the return object by calling collect(subArrayVk, ...rest) for each subarray
  const ret: Record<string, any> = {};
  Object.keys(subArrays).forEach(vk => ret[vk] = collect(subArrays[vk], ...rest));
  return ret;
}

因為函式的呼叫簽名回傳通用條件型別,所以最容易使函式成為單呼叫簽名多載,以便松散地檢查實作。這只是意味著我們在實作之前有一個宣告的呼叫簽名:

// call signature
function collect<K extends (keyof T)[], T extends object>(
  arr: (T & Record<K[number], string>)[], ...keys: K): Collect<K>;

// implementation
function collect(arr: any[], ...keys: string[]) {
  // ? snip, see above
}

好吧,讓我們測驗一下:

const outp = collect(inp, "a", "b", "c");
console.log(outp);
// {x:{u: ["q","s"], v:["r","t"]}, y:{u:["q","r"], v:["s"]}}

這樣可行!你的例子:

const x = collect(arr, "make", "classification", "segment", "model", "catalogDetail");
console.log(x);
/* {
  "Acura": {
    "Mid SUV": {
      "Competitive Trucks": {
        "RDX": [
          "RDX_SUV_4_Gasoline_2013_Base w/Tech_FWD_3.5_6_105.7_Automatic"
        ]
      }
    },
    "Midsize Car": {
      "Competitive Cars": {
        "TSX": [
          "TSX_Sedan_4_Gasoline_2012_Base w/Tech_FWD_2.4_4_106.4_Automatic"
        ]
      }
    }
  },
  "Aston Martin": {
    "Compact Car": {
      "Competitive Cars": {
        "DB11": [
          "DB11_Convertible_2_Gasoline_2019_Volante_RWD_4.0_8_110.4_Automatic"
        ]
      }
    }
  }
}   */

那也行!

游樂場代碼鏈接

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/537237.html

標籤:有角度的打字稿目的嵌套嵌套循环

上一篇:如何在typeScript中使用模板文字連接兩個字串?

下一篇:Angular2選擇表單不捕獲值

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more