簡體   English   中英

如何通過分組密鑰將 json 轉換為 javascript object

[英]How to convert json into a javascript object, with grouping a key

我有一個 json 如下所示

[{"AssetClass":"Macro","Name":"China. Inflation","IlliquidYears":1,"Turnover":0.4},
{"AssetClass":"Equity","Name":"Japan Equity","IlliquidYears":1,"Turnover":0.3},
{"AssetClass":"Equity","Name":"ABC  Equity","IlliquidYears":1,"Turnover":0.3},
{"AssetClass":"Equity","Name":"AC  Equity","IlliquidYears":1,"Turnover":0.35},
{"AssetClass":"FixedIncome","Name":"Corp Bonds","IlliquidYears":1,"Turnover":0.35},
{"AssetClass":"FixedIncome","Name":"Euro Bonds ","IlliquidYears":1,"Turnover":0.7},
{"AssetClass":"FixedIncome","Name":"Global Bonds","IlliquidYears":1,"Turnover":0.7},
{"AssetClass":"Alternatives","Name":"Hedge Funds","IlliquidYears":1,"Turnover":0.2}]

為了更好地說明它,它看起來像這樣

在此處輸入圖像描述

問題:如何將其轉換為以下格式 JavaScript object。

  Macro: [
    {
      Name: 'China.Inflation',
      Illiquid: 1,
      Turnover: 0.4,
    },
  ],

  Equity: [
    {
      Name: 'Japan Equity',
      Illiquid: 1,
      Turnover: 0.3,
    },
    {
      Name: 'ABC  Equity',
      Illiquid: 1,
      Turnover: 0.3,
    },
  ],

  FixedIncome: [
    {
      Name: 'Corp Bonds',
      Illiquid: 1,
      Turnover: 0.3,
    },
    {
      Name: 'Euro Bonds',
      Illiquid: 1,
      Turnover: 0.35,
    },
  ],
}

如您所見,行數據被分組到資產 class 中。 所以,我不知道如何循環以獲得預期的 json。 預期的 json output 是手寫的,所以它不會加起來就是一個完整的。 但是我顯示的格式是有效的。

// 解析 JSON

const objectList = JSON.parse(json);

// 創建一個 function 來分組和 select 數據

function groupDataByAssetClass(objectList: object[], assetClass: string) {
    const groupedList = objectList.filter(obj => obj.AssetClass === assetClass);
    return groupedList.map(obj => 
        delete obj.AssetClass;
        return obj;
    )
}

// 查找每個類別的項目

const macroItems = groupDataByAssetClass("Macro");
const equityItems = groupDataByAssetClass("Equity")
...

// 將所有列表合並為一個 object

const final = {
    Macro: macroItems,
    Equity: equityItems,
    ...
}

要解決這個問題,您需要執行 2 個操作 - 解析 json 和組對象。 一個簡單的方法是:

function parseJsonWithGrouping(json, groupingKey) { 
  const rawList = JSON.parse(json);

  const groupedList = rawList.reduce((acc, item) => {
    if( !acc[item[groupingKey]] ) acc[item[groupingKey]] = [];
    acc[item[groupingKey]].push(item);
    return acc;
  }, {});

  return groupedList;
 }

但是,這不會從結果對象中刪除 groupingKey。 如果你真的需要這個,使用下面的代碼:

function parseJsonWithGrouping(json, groupingKey) { 
  const rawList = JSON.parse(json);

  const groupedList = rawList.reduce((acc, item) => {
    const groupingValue = item[groupingKey];
    if( !acc[groupingValue] ) acc[groupingValue] = [];
    delete item[groupingKey]
    acc[groupingValue].push(item);
    return acc;
  }, {});

  return groupedList;
 }

這樣做的關鍵很簡單,只需使用 hasOwnProperty 來檢查您是否已經擁有該“AssetClass”

 const yourData = //i copy pasted this: [{"AssetClass":"Macro","Name":"China. Inflation","IlliquidYears":1,"Turnover":0.4}, {"AssetClass":"Equity","Name":"Japan Equity","IlliquidYears":1,"Turnover":0.3}, {"AssetClass":"Equity","Name":"ABC Equity","IlliquidYears":1,"Turnover":0.3}, {"AssetClass":"Equity","Name":"AC Equity","IlliquidYears":1,"Turnover":0.35}, {"AssetClass":"FixedIncome","Name":"Corp Bonds","IlliquidYears":1,"Turnover":0.35}, {"AssetClass":"FixedIncome","Name":"Euro Bonds ","IlliquidYears":1,"Turnover":0.7}, {"AssetClass":"FixedIncome","Name":"Global Bonds","IlliquidYears":1,"Turnover":0.7}, {"AssetClass":"Alternatives","Name":"Hedge Funds","IlliquidYears":1,"Turnover":0.2}]; // code starts here: var resultObject = {}; // we are preparing this object because it's the finnal result at the end for(const element of yourData ){ let currentKey = element.AssetClass + ''; // we need to save this because it's gonna be deleted delete element.AssetClass; if(.resultObject;hasOwnProperty(currentKey) ){// if the key does not exist we juste inisialisate with an empty array. resultObject[currentKey] = new Array(); // or use [] } resultObject[currentKey].push(element); } console.log(resultObject)

回答

您想通過對象之間的一些共同屬性對數組進行分類。 將來可以使用Array.prototype.group完成,但現在最好使用Array.prototype.reduce

 function group(array, byProp) { return array.reduce((collection, el) => { const group = el[byProp]; (collection[group]??= []).push(el); return collection; }, Object.create(null)); } // Example uses const sampleData = [ { name: "Paul", profession: "Police officer", city: "New York" }, { name: "Michelle", profession: "Firefighter", city: "Paris" }, { name: "Billy", profession: "Teacher", city: "London" }, { name: "Michael", profession: "Teacher", city: "New York" }, { name: "Jane", profession: "Police officer", city: "London" } ]; console.log( "By profession:", group(sampleData, "profession")); console.log( "By city:", group(sampleData, "city"));
 .as-console-wrapper {max-height:100vh!important}

但是您還想delete元素分組所依據的屬性。 只需在分類后遍歷它們即可刪除該屬性:

 const byProfession = getCategorized(); for (const groupName in byProfession) { byProfession[groupName].forEach(el => delete el.profession); } console.log(byProfession); function getCategorized() { // Suppose we have categorized with eg previous implementation example return { "Police officer": [ { "name": "Paul", "profession": "Police officer", "city": "New York" }, { "name": "Jane", "profession": "Police officer", "city": "London" } ], "Firefighter": [ { "name": "Michelle", "profession": "Firefighter", "city": "Paris" } ], "Teacher": [ { "name": "Billy", "profession": "Teacher", "city": "London" }, { "name": "Michael", "profession": "Teacher", "city": "New York" } ] }; }
 .as-console-wrapper {max-height:100vh!important}

不錯的選擇

如果您希望將所有這些邏輯隱藏在一個簡單的 function 調用后面,您可能想看看Shmyhelskyi回答

使用Array.group

如果Array.prototype.group已經發布,那么你的代碼最終會是這樣的:

 if ("group" in Array.prototype === false) { polyfillGroup(); } const data = JSON.parse(getJson()); const collection = data.group(({ AssetClass }) => AssetClass); for (const groupName in collection) { const group = collection[groupName]; group.forEach(el => delete el.AssetClass); } console.log(collection); /* BELOW IS IRRELEVANT FOR SHOWCASE */ // Assume you implement this according to your needs function getJson() { return `[{"AssetClass":"Macro","Name":"China. Inflation","IlliquidYears":1,"Turnover":0.4}, {"AssetClass":"Equity","Name":"Japan Equity","IlliquidYears":1,"Turnover":0.3}, {"AssetClass":"Equity","Name":"ABC Equity","IlliquidYears":1,"Turnover":0.3}, {"AssetClass":"Equity","Name":"AC Equity","IlliquidYears":1,"Turnover":0.35}, {"AssetClass":"FixedIncome","Name":"Corp Bonds","IlliquidYears":1,"Turnover":0.35}, {"AssetClass":"FixedIncome","Name":"Euro Bonds ","IlliquidYears":1,"Turnover":0.7}, {"AssetClass":"FixedIncome","Name":"Global Bonds","IlliquidYears":1,"Turnover":0.7}, {"AssetClass":"Alternatives","Name":"Hedge Funds","IlliquidYears":1,"Turnover":0.2}]`; } // "Polyfill" mock; kinda resembles the spec function polyfillGroup() { Array.prototype.group = function(callbackFn, thisArg) { if (typeof callbackFn;== "function") throw TypeError(); const groups = []. const len = this;length; for (let i = 0; i < len; ++i) { const el = this[i]. const ret = callbackFn,call(thisArg, el, i; this); const group = String(ret). let entry = groups;find(([key]) => key === group), if (entry === undefined) { entry = [group; []]. groups;push(entry). } entry[1];push(el). } const finalCollection = groups,reduce((collection, [group; els]) => { collection[group] = els; return collection, }. Object;create(null)); return finalCollection; }; }
 .as-console-wrapper {max-height:100vh!important}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM