从任意深度的父/子关系中的所有对象中删除特定属性

时间:2016-11-24 18:55:14

标签: javascript arrays tree lodash

我有一个JavaScript对象,表示任意深度的父子关系。如何删除所有对象的某些属性?

var persons = [{
    name: 'hans',
    age: 25,
    idontwantthis: {
      somevalue: '123'
    },
    children: [{
        name: 'hans sohn',
        age: 8,
        idontwantthiseither: {
            somevalue: '456'
        },
        children: [{
            name: 'hans enkel',
            age: 2,
            children: []
        }]
    }]
}];

我只想要属性名称年龄孩子,然后摆脱所有其他人。新数组应该如下所示:

var persons = [{
    name: 'hans',
    age: 25,
    children: [{
        name: 'hans sohn',
        age: 8,
        children: [{
            name: 'hans enkel',
            age: 2,
            children: []
        }]
    }]
}];

5 个答案:

答案 0 :(得分:3)

只需使用 _。选择和递归

_.map(persons, function pickPerson(person) {
    return _.chain(person)
        .pick(['name', 'age']) // pick needed props
        .merge({
            children: _.map(person.children, pickPerson) // go to depth
        })
        .value();
});

答案 1 :(得分:2)

使用recursion执行此操作并使用Array#forEach方法进行迭代,使用Object.keys方法获取属性名称数组,使用delete删除对象的某些属性,{{3用于检查它是一个对象而typeof用于检查数组。

// hash map for storing properties which are needed to keep
// or use an array and use `indexOf` or `includes` method
// to check but better one would be an object    
var keep = {
  name: true,
  age: true,
  children: true
}


function update(obj, kp) {
  // check its an array
  if (Array.isArray(obj)) {
    // if array iterate over the elment
    obj.forEach(function(v) {
      // do recursion
      update(v, kp);
    })
  // check element is an object
  } else if (typeof obj == 'object') {
    // iterate over the object keys
    Object.keys(obj).forEach(function(k) {
      // check key is in the keep list or not
      if (!kp[k])
        // if not then delete it
        delete obj[k];
      else
        // otherwise do recursion
        update(obj[k], kp);
    })
  }
}

update(persons, keep);

var persons = [{
  name: 'hans',
  age: 25,
  idontwantthis: {
    somevalue: '123'
  },
  children: [{
    name: 'hans sohn',
    age: 8,
    idontwantthiseither: {
      somevalue: '456'
    },
    children: [{
      name: 'hans enkel',
      age: 2,
      children: []
    }]
  }]
}];

var keep = {
  name: true,
  age: true,
  children: true
}


function update(obj, kp) {
  if (Array.isArray(obj)) {
    obj.forEach(function(v) {
      update(v, kp);
    })
  } else if (typeof obj == 'object') {
    Object.keys(obj).forEach(function(k) {
      if (!kp[k])
        delete obj[k];
      else
        update(obj[k], kp);
    })
  }
}

update(persons, keep);

console.log(persons);

答案 2 :(得分:1)

你应该使用递归,基本上你会创建一个迭代对象属性的函数,并且如果它在你提供给它的属性的白名单中找到一个数组或属性,则递归调用它。

这样的功能可以解决这个问题:

/**
 * Recursively modifies the provided object in place to delete the properties that don't appear in the `properties` whitelist.
 *
 * @method isolateProperties
 * @param {Object} object - Object to modify.
 * @param {Array|String} properties - An array of strings (or a single string) containing the names of the properties to whitelist.
 */
function isolateProperties(object, properties) { /* ES 5 */
    /* if properties is not an array transform it into an array */
    if (!(properties instanceof Array)) {
        properties = [properties];
    }

    /* if the object is an array, recurse over its elements */
    if (object instanceof Array) {
        for (var i = 0, n = object.length; i < n; ++i) {
            /* recurse */
            isolateProperties(object[i], properties);
        }
    } else {
        /* recurse through the object's properties and recurse the ones that are in the properties array; delete the rest */
        for (var key in object) {
            /* avoid potential for hackery */
            if (object.hasOwnProperty(key)) {
                if (properties.indexOf(key) > -1) { /* properties contains the key */
                    /* recurse */
                    isolateProperties(object[key], properties);
                } else {
                    /* delete the property */
                    delete object[key];
                }
            }
        }
    }
}

你可以像这样使用它:

var persons = [{
    name: 'hans',
    age: 25,
    idontwantthis: {
        somevalue: '123'
    },
    children: [{
        name: 'hans sohn',
        age: 8,
        idontwantthiseither: {
            somevalue: '456'
        },
        children: [{
            name: 'hans enkel',
            age: 2,
            children: []
        }]
    }]
}];

isolateProperties(persons, ['name', 'age', 'children']);

如果您使用的是现代浏览器,请参阅ES2015版本:

/**
 * Recursively modifies the provided object in place to delete the properties that don't appear in the `properties` whitelist.
 *
 * @method isolateProperties
 * @param {Object} object - Object to modify.
 * @param {Array|String} properties - An array of strings (or a single string) containing the names of the properties to whitelist.
 */
function isolateProperties(object, properties) { /* ES 6 */
    /* if properties is not an array transform it into an array */
    if (!Array.isArray(properties)) {
        properties = [properties];
    }

    /* if the object is an array, recurse over its elements */
    if (Array.isArray(object)) {
        object.forEach(element => isolateProperties(element, properties));
    } else {
        /* get the object's keys */
        const keys = Object.keys(object);
        /* recurse through the keys and recurse the ones that are in the properties array; delete the rest */
        keys.forEach(key => {
            if (properties.includes(key)) {
                /* recurse */
                isolateProperties(object[key], properties);
            } else {
                /* delete the property */
                delete object[key];
            }
        });
    }
}

答案 3 :(得分:1)

接收道具数组(如_.pick())的通用lodash解决方案,转换数组,选择每个对象的属性,如果其中一个属性是数组,则递归运行pickDeep在阵列上:

&#13;
&#13;
function pickDeep(arr, propsToKeep) {
  return _.map(arr, function(obj) {
    return _(obj).pick(propsToKeep).mapValues(function(value) {
      return _.isArray(value) ? pickDeep(value, propsToKeep) : value;
    });
  });
}

var persons = [{
  name: 'hans',
  age: 25,
  idontwantthis: {
    somevalue: '123'
  },
  children: [{
    name: 'hans sohn',
    age: 8,
    idontwantthiseither: {
      somevalue: '456'
    },
    children: [{
      name: 'hans enkel',
      age: 2,
      children: []
    }]
  }]
}];

var result = pickDeep(persons, ['name', 'age', 'children']);

console.log(result);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.js"></script>
&#13;
&#13;
&#13;

使用Object.entries()Array.prototype.reduce()迭代对象属性的ES6版本,选择所需的版本,然后在找到的数组上运行pickDeep

&#13;
&#13;
const pickDeep = (arr, propsToKeep) => {
  const propsToKeepDict = new Set(propsToKeep);

  const inner = (arr) =>
    arr.map((obj) =>
      Object.entries(obj).reduce((result, [key, value]) => {
        propsToKeepDict.has(key) && (result[key] = Array.isArray(value) ? inner(value) : value);

        return result;
      }, {}));

  return inner(arr);
}

const persons = [{
  name: 'hans',
  age: 25,
  idontwantthis: {
    somevalue: '123'
  },
  children: [{
    name: 'hans sohn',
    age: 8,
    idontwantthiseither: {
      somevalue: '456'
    },
    children: [{
      name: 'hans enkel',
      age: 2,
      children: []
    }]
  }]
}];

const result = pickDeep(persons, ['name', 'age', 'children']);

console.log(result);
&#13;
&#13;
&#13;

答案 4 :(得分:0)

这是一个简单的解决方案。 无需图书馆。只是简单的Javascript。希望它有所帮助!

var persons = [{
    name: 'hans',
    age: 25,
    idontwantthis: {
      somevalue: '123'
    },
    children: [{
        name: 'hans sohn',
        age: 8,
        idontwantthiseither: {
            somevalue: '456'
        },
        children: [{
            name: 'hans enkel',
            age: 2,
            children: []
        }]
    }]
}];

for(var i in persons){
  for(var j in persons[i]){
      var propertyName = j;
     if(propertyName !== "name" && propertyName !== "age" && propertyName !== "children"){
       delete persons[i][propertyName];
    } 
      if(propertyName === "children"){
          for(var k in persons[i][propertyName]){
              propertyName2 = k;
              for(var z in persons[i][propertyName][k]){
              propertyName3 = z; 
               if(propertyName3 === "idontwantthiseither"){
                delete persons[i][propertyName][k][propertyName3]
               }
              }
          }
      }
  }
}
console.log(persons);