[英]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.