[英]Renaming object keys recursively
我有一個遞歸函數來重命名對象的鍵名,但我無法弄清楚如何重命名其中的 2 個鍵(問題鍵是對象)
我認為問題在於我在哪里檢查對象類型,但此時如何重命名密鑰?
實際的數組非常大,但下面是一個精簡版。
任何幫助表示贊賞。
var keys_short = ['ch','d','u','tz'];
var keys_long = ['children','data','user_id','time_zone'];
function refit_keys(o){
build = {};
for (var i in o){
if(typeof(o[i])=="object"){
o[i] = refit_keys(o[i]);
build = o;
}else{
var ix = keys_short.indexOf(i);
if(ix!=-1){
build[keys_long[ix]] = o[keys_short[ix]];
}
}
}
return build;
}
我的輸入如下所示:
{
"id":"1",
"ch":[
{
"id":"3",
"ch":[
],
"d":{
"u":"3",
"tz":"8.00"
}
},
{
"id":"45",
"ch":[
{
"id":"70",
"ch":[
{
"id":"43",
"ch":[
],
"d":{
"u":"43",
"tz":"-7.00"
}
}
],
"d":{
"u":"70",
"tz":"-7.00"
}
}
],
"d":{
"u":"45",
"tz":"-7.00"
}
}
],
"d":{
"u":"1",
"tz":"8.00"
}
}
我的輸出是這樣的:
{
"id":"1",
"ch":[
{
"id":"3",
"ch":[
],
"d":{
"user_id":"3",
"time_zone":"8.00"
}
},
{
"id":"45",
"ch":[
{
"id":"70",
"ch":[
{
"id":"43",
"ch":[
],
"d":{
"user_id":"43",
"time_zone":"-7.00"
}
}
],
"d":{
"user_id":"70",
"time_zone":"-7.00"
}
}
],
"d":{
"user_id":"45",
"time_zone":"-7.00"
}
}
],
"d":{
"user_id":"1",
"time_zone":"8.00"
}
}
那里有幾個問題。
一是您因為未能在函數中聲明您的build
變量而成為隱式全局變量的犧牲品。
但邏輯也有問題,這里有一個最小的返工:
var keys_short = ["ch","d","u","tz"];
var keys_long = ["children","data","user_id","time_zone"];
function refit_keys(o){
var build, key, destKey, ix, value;
// Only handle non-null objects
if (o === null || typeof o !== "object") {
return o;
}
// Handle array just by handling their contents
if (Array.isArray(o)) {
return o.map(refit_keys);
}
// We have a non-array object
build = {};
for (key in o) {
// Get the destination key
ix = keys_short.indexOf(key);
destKey = ix === -1 ? key : keys_long[ix];
// Get the value
value = o[key];
// If this is an object, recurse
if (typeof value === "object") {
value = refit_keys(value);
}
// Set it on the result using the destination key
build[destKey] = value;
}
return build;
}
現場示例:
"use strict"; var input = { "id":"1", "ch":[ { "id":"3", "ch":[ ], "d":{ "u":"3", "tz":"8.00" } }, { "id":"45", "ch":[ { "id":"70", "ch":[ { "id":"43", "ch":[ ], "d":{ "u":"43", "tz":"-7.00" } } ], "d":{ "u":"70", "tz":"-7.00" } } ], "d":{ "u":"45", "tz":"-7.00" } } ], "d":{ "u":"1", "tz":"8.00" } }; var keys_short = ["ch","d","u","tz"]; var keys_long = ["children","data","user_id","time_zone"]; function refit_keys(o){ var build, key, destKey, ix, value; // Only handle non-null objects if (o === null || typeof o !== "object") { return o; } // Handle array just by handling their contents if (Array.isArray(o)) { return o.map(refit_keys); } // We have a non-array object build = {}; for (key in o) { // Get the destination key ix = keys_short.indexOf(key); destKey = ix === -1 ? key : keys_long[ix]; // Get the value value = o[key]; // If this is an object, recurse if (typeof value === "object") { value = refit_keys(value); } // Set it on the result using the destination key build[destKey] = value; } return build; } console.log(refit_keys(input));
.as-console-wrapper { max-height: 100% !important; }
但不是並行數組,我建議使用映射,通過對象或Map
:
// Object with no prototype to avoid false matches on `toString` and other built-ins
var mapShortToLong = Object.assign(Object.create(null), {
"ch": "children",
"d": "data",
"u": "user_id",
"tz": "time_zone"
});
function refit_keys(o){
var build, key, destKey, value;
// Only handle non-null objects
if (o === null || typeof o !== "object") {
return o;
}
// Handle array just by handling their contents
if (Array.isArray(o)) {
return o.map(refit_keys);
}
build = {};
for (key in o) {
// Get the destination key
destKey = mapShortToLong[key] || key;
// Get the value
value = o[key];
// If this is an object, recurse
if (typeof value === "object") {
value = refit_keys(value);
}
// Set it on the result using the destination key
build[destKey] = value;
}
return build;
}
現場示例:
"use strict"; var input = { "id":"1", "ch":[ { "id":"3", "ch":[ ], "d":{ "u":"3", "tz":"8.00" } }, { "id":"45", "ch":[ { "id":"70", "ch":[ { "id":"43", "ch":[ ], "d":{ "u":"43", "tz":"-7.00" } } ], "d":{ "u":"70", "tz":"-7.00" } } ], "d":{ "u":"45", "tz":"-7.00" } } ], "d":{ "u":"1", "tz":"8.00" } }; // Object with no prototype to avoid false matches on `toString` and other built-ins var mapShortToLong = Object.assign(Object.create(null), { "ch": "children", "d": "data", "u": "user_id", "tz": "time_zone" }); function refit_keys(o){ var build, key, destKey, value; // Only handle non-null objects if (o === null || typeof o !== "object") { return o; } // Handle array just by handling their contents if (Array.isArray(o)) { return o.map(refit_keys); } build = {}; for (key in o) { // Get the destination key destKey = mapShortToLong[key] || key; // Get the value value = o[key]; // If this is an object, recurse if (typeof value === "object") { value = refit_keys(value); } // Set it on the result using the destination key build[destKey] = value; } return build; } console.log(refit_keys(input));
.as-console-wrapper { max-height: 100% !important; }
或者在現代 JavaScript 中:
// Using a `Map` here to provide a `Map` example, but you can ue an object as
// in the previous ones if you prefer if the keys are strings
const mapShortToLong = new Map([
["ch", "children"],
["d", "data"],
["u", "user_id"],
["tz", "time_zone"],
]);
function refit_keys(o){
// Only handle non-null objects
if (o === null || typeof o !== "object") {
return o;
}
// Handle array just by handling their contents
if (Array.isArray(o)) {
return o.map(refit_keys);
}
const build = {};
for (const key in o) {
// Get the destination key
const destKey = mapShortToLong.get(key) || key;
// Get the value
let value = o[key];
// If this is an object, recurse
if (typeof value === "object") {
value = refit_keys(value);
}
// Set it on the result using the destination key
build[destKey] = value;
}
return build;
}
現場示例:
"use strict"; var input = { "id":"1", "ch":[ { "id":"3", "ch":[ ], "d":{ "u":"3", "tz":"8.00" } }, { "id":"45", "ch":[ { "id":"70", "ch":[ { "id":"43", "ch":[ ], "d":{ "u":"43", "tz":"-7.00" } } ], "d":{ "u":"70", "tz":"-7.00" } } ], "d":{ "u":"45", "tz":"-7.00" } } ], "d":{ "u":"1", "tz":"8.00" } }; // Using a `Map` here to provide a `Map` example, but you can ue an object as // in the previous ones if you prefer if the keys are strings const mapShortToLong = new Map([ ["ch", "children"], ["d", "data"], ["u", "user_id"], ["tz", "time_zone"], ]); function refit_keys(o){ // Only handle non-null objects if (o === null || typeof o !== "object") { return o; } // Handle array just by handling their contents if (Array.isArray(o)) { return o.map(refit_keys); } const build = {}; for (const key in o) { // Get the destination key const destKey = mapShortToLong.get(key) || key; // Get the value let value = o[key]; // If this is an object, recurse if (typeof value === "object") { value = refit_keys(value); } // Set it on the result using the destination key build[destKey] = value; } return build; } console.log(refit_keys(input));
.as-console-wrapper { max-height: 100% !important; }
有點晚了,但我正在尋找一個很好的簡短實現,它也處理數組(前面的答案沒有),所以我決定發布我的通用 ES6 實現,因為它可能對某些人有所幫助:
function deepMapKeys(originalObject, callback) {
if (typeof originalObject !== 'object') {
return originalObject
}
return Object.keys(originalObject || {}).reduce((newObject, key) => {
const newKey = callback(key)
const originalValue = originalObject[key]
let newValue = originalValue
if (Array.isArray(originalValue)) {
newValue = originalValue.map(item => deepMapKeys(item, callback))
} else if (typeof originalValue === 'object') {
newValue = deepMapKeys(originalValue, callback)
}
return {
...newObject,
[newKey]: newValue,
}
}, {})
}
對於有問題的案例,調用將是:
deepMapKeys(inputObject, key => (keys_long[keys_short.indexOf(key)] || key))
問題之一可能是變量build
實際上是一個全局變量。 因此,它只包含遞歸中第一個深度的結果。
在build
之前添加一個var
應該可以解決部分問題。
我喜歡這種方法。 但我偶然發現了這一點:
你這樣稱呼它: deepMapKeys({testValue:["justString"]}, key => (key));
返回值包含:
{0: "j", 1: "u", 2: "s", 3: "t", 4: "S", 5: "t", 6: "r", 7: "i", 8: "n", 9: "g"}
長度:1
會說,它將我的字符串轉換為數組。
對象鍵遞歸映射函數的更簡潔實現:
const objectRecursiveKeyMap = (obj, fn) =>
Object.fromEntries(Object.entries(obj).map(([key, value]) => {
const getValue = v =>
(typeof v === 'object' && v !== null) ? objectRecursiveKeyMap(v, fn) : v
return [fn(key), Array.isArray(value) ? value.map(val => getValue(val)) : getValue(value)]
}))
使用示例:
objectRecursiveKeyMap(obj, key => key.toUpperCase())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.