递归重命名对象键 [英] Renaming object keys recursively
问题描述
我有一个递归函数来重命名对象的键名,但我无法弄清楚如何重命名其中的 2 个键(问题键是对象)
I have a recursive function to rename the key names of an object but I'm unable to figure out how to rename 2 of the keys (problem keys are objects)
我认为问题在于我在哪里检查对象类型,但此时如何重命名密钥?
I think the problem is where I'm checking for object type but how can I rename the key at that point?
实际的数组非常大,但下面是精简版.
The actual arrays are very large but a cut down version is below.
感谢任何帮助.
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
变量.
但是逻辑也有问题,这里有一个最小的返工:
But the logic has issues as well, here's a minimal reworking:
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
:
But rather than parallel arrays, I'd suggest using a mapping, via an object or a 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 中:
Or in modern 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;
}
这篇关于递归重命名对象键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!