使用 JavaScript 以递归方式从对象中删除属性和值的最快方法是什么?
Using JavaScript what's the quickest way to recursively remove properties and values from an object?
我需要找到从对象中删除所有 $meta
属性及其值的最快方法,例如:
{
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
鉴于 $meta
属性 可能位于对象中的任何位置,因此可能需要某种形式的递归,因此
应该变为以下形式。
{
"part_one": {
"name": "My Name",
"something": "123"
},
"part_two": [
{
"name": "name",
"dob": "dob"
},
{
"name": "name",
"dob": "dob"
}
]
}
如有任何帮助或建议,我们将不胜感激!
谢谢!
// Helper function
function removeProps(obj,keys){
if(Array.isArray(obj)){
obj.forEach(function(item){
removeProps(item,keys)
});
}
else if(typeof obj === 'object' && obj != null){
Object.getOwnPropertyNames(obj).forEach(function(key){
if(keys.indexOf(key) !== -1)delete obj[key];
else removeProps(obj[key],keys);
});
}
}
// The object we want to iterate
var obj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
};
// Utilize the utility
removeProps(obj,['$meta']);
// Show the result
document.body.innerHTML = '<pre>' + JSON.stringify(obj,null,4) + '</pre>';
一个简单的自调用函数就可以做到
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
var myObj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
removeMeta(myObj);
console.log(myObj);
正如@floor 上面评论的那样:
JSON.parse(JSON.stringify(obj, (k,v) => (k === '$meta')? undefined : v))
(抱歉,我的声望值还不够,无法直接发表评论。)
仅供参考,typeof null === 'object',因此在@joseph-marikle 提供的 removeMeta() 示例中,该函数将递归空值。
在此处阅读更多内容:why is typeof null "object"?
这是一个函数,它接受一个字符串或一个字符串数组来递归删除(基于 Joseph 的回答):
// removes all propsToRemove (passed as an array or string), drilling down up to maxLevel times
// will modify the input and return it
du.removeAllPropsFromObj = function(obj, propsToRemove, maxLevel) {
if (typeof maxLevel !== "number") maxLevel = 10
for (var prop in obj) {
if (typeof propsToRemove === "string" && prop === propsToRemove)
delete obj[prop];
else if (propsToRemove.indexOf(prop) >= 0) // it must be an array
delete obj[prop];
else if (typeof obj[prop] === "object" && maxLevel>0)
du.removeAllPropsFromObj(obj[prop], propsToRemove, maxLevel-1);
}
return obj
}
当any key在对象中的any level时,我使用@的引用函数创建了这个函数约瑟夫·马里克尔
const _ = require("lodash");
const isObject = obj => obj != null && obj.constructor.name === "Object";
const removeAttrDeep = (obj, key) => {
for (prop in obj) {
if (prop === key) delete obj[prop];
else if (_.isArray(obj[prop])) {
obj[prop] = obj[prop].filter(k => {
return !_.isEmpty(removeAttrDeep(k, key));
});
} else if (isObject(obj[prop])) removeAttrDeep(obj[prop], key);
}
return obj;
};
示例:
const _obj = {
a: "b", b: "e", c: { a: "a", b: "b", c: "c"},
d: [ { a: "3" }, { b: ["2", "3"] }]};
console.log(removeAttrDeep(_obj, "b"));
// recursively delete a key from anywhere in the object
// will mutate the obj - no need to return it
const deletePropFromObj = (obj, deleteThisKey) => {
if (Array.isArray(obj)) {
obj.forEach(element => deletePropFromObj(element, deleteThisKey))
} else if (typeof obj === 'object') {
for (const key in obj) {
const value = obj[key]
if (key === deleteThisKey) delete obj[key]
else deletePropFromObj(value, deleteThisKey)
}
}
}
deletePropFromObj(obj, '$meta');
这应该可以避免循环引用的任何问题
const recursiveRedact = <T extends Object>(obj: T, keys: Set<string>, visitedIn?: Set<any>): T => {
if (typeof obj !== 'object') return obj;
const visited = visitedIn ?? new Set();
visited.add(obj);
Object.entries(obj).forEach(([key, val]) => {
if (keys.has(key)) {
obj[key as keyof T] = '[redacted]' as any;
} else if (typeof val === 'object' && !visited.has(val)) {
recursiveRedact(val, keys, visited);
}
});
return obj;
};
我需要找到从对象中删除所有 $meta
属性及其值的最快方法,例如:
{
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
鉴于 $meta
属性 可能位于对象中的任何位置,因此可能需要某种形式的递归,因此
应该变为以下形式。
{
"part_one": {
"name": "My Name",
"something": "123"
},
"part_two": [
{
"name": "name",
"dob": "dob"
},
{
"name": "name",
"dob": "dob"
}
]
}
如有任何帮助或建议,我们将不胜感激!
谢谢!
// Helper function
function removeProps(obj,keys){
if(Array.isArray(obj)){
obj.forEach(function(item){
removeProps(item,keys)
});
}
else if(typeof obj === 'object' && obj != null){
Object.getOwnPropertyNames(obj).forEach(function(key){
if(keys.indexOf(key) !== -1)delete obj[key];
else removeProps(obj[key],keys);
});
}
}
// The object we want to iterate
var obj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
};
// Utilize the utility
removeProps(obj,['$meta']);
// Show the result
document.body.innerHTML = '<pre>' + JSON.stringify(obj,null,4) + '</pre>';
一个简单的自调用函数就可以做到
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
var myObj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
removeMeta(myObj);
console.log(myObj);
正如@floor 上面评论的那样:
JSON.parse(JSON.stringify(obj, (k,v) => (k === '$meta')? undefined : v))
(抱歉,我的声望值还不够,无法直接发表评论。)
仅供参考,typeof null === 'object',因此在@joseph-marikle 提供的 removeMeta() 示例中,该函数将递归空值。
在此处阅读更多内容:why is typeof null "object"?
这是一个函数,它接受一个字符串或一个字符串数组来递归删除(基于 Joseph 的回答):
// removes all propsToRemove (passed as an array or string), drilling down up to maxLevel times
// will modify the input and return it
du.removeAllPropsFromObj = function(obj, propsToRemove, maxLevel) {
if (typeof maxLevel !== "number") maxLevel = 10
for (var prop in obj) {
if (typeof propsToRemove === "string" && prop === propsToRemove)
delete obj[prop];
else if (propsToRemove.indexOf(prop) >= 0) // it must be an array
delete obj[prop];
else if (typeof obj[prop] === "object" && maxLevel>0)
du.removeAllPropsFromObj(obj[prop], propsToRemove, maxLevel-1);
}
return obj
}
当any key在对象中的any level时,我使用@的引用函数创建了这个函数约瑟夫·马里克尔
const _ = require("lodash");
const isObject = obj => obj != null && obj.constructor.name === "Object";
const removeAttrDeep = (obj, key) => {
for (prop in obj) {
if (prop === key) delete obj[prop];
else if (_.isArray(obj[prop])) {
obj[prop] = obj[prop].filter(k => {
return !_.isEmpty(removeAttrDeep(k, key));
});
} else if (isObject(obj[prop])) removeAttrDeep(obj[prop], key);
}
return obj;
};
示例:
const _obj = {
a: "b", b: "e", c: { a: "a", b: "b", c: "c"},
d: [ { a: "3" }, { b: ["2", "3"] }]};
console.log(removeAttrDeep(_obj, "b"));
// recursively delete a key from anywhere in the object
// will mutate the obj - no need to return it
const deletePropFromObj = (obj, deleteThisKey) => {
if (Array.isArray(obj)) {
obj.forEach(element => deletePropFromObj(element, deleteThisKey))
} else if (typeof obj === 'object') {
for (const key in obj) {
const value = obj[key]
if (key === deleteThisKey) delete obj[key]
else deletePropFromObj(value, deleteThisKey)
}
}
}
deletePropFromObj(obj, '$meta');
这应该可以避免循环引用的任何问题
const recursiveRedact = <T extends Object>(obj: T, keys: Set<string>, visitedIn?: Set<any>): T => {
if (typeof obj !== 'object') return obj;
const visited = visitedIn ?? new Set();
visited.add(obj);
Object.entries(obj).forEach(([key, val]) => {
if (keys.has(key)) {
obj[key as keyof T] = '[redacted]' as any;
} else if (typeof val === 'object' && !visited.has(val)) {
recursiveRedact(val, keys, visited);
}
});
return obj;
};