Lodash 递归删除项目

IT技术 javascript lodash
2021-03-09 08:09:12

给定这个 JSON 对象,lodash 如何reach从对象中删除值?

{ 
    total: 350,
    SN1: { 
        reach: 200,
        engagementRate: 1.35
    },
    SN2: {
        reach: 150,
        engagementRate: 1.19
    }
}

我一直在尝试迭代 remove() 它,但我总是得到一个未定义的对象作为回报,所以我肯定我做错了。这也是我第一次使用 lodash,所以这可能是实际问题。

任何人都可以帮忙吗?

6个回答

_.transform()将对象传递给另一个对象,并在将值传递给新对象时,检查该值是否为对象以及它是否具有 'reach' 属性,如果是,则_.omit()用于获取不带reach以下内容的新对象

var obj = {
  total: 350,
  SN1: {
    reach: 200,
    engagementRate: 1.35
  },
  SN2: {
    reach: 150,
    engagementRate: 1.19
  }
};

var result = _.transform(obj, function(result, value, key) {
  result[key] = _.isObject(value) && `reach` in value ? _.omit(value, 'reach') : value;
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

如果您需要一个递归解决方案来处理多个嵌套对象级别,这里是deepOmit,它使用相同的想法,但没有_.omit, 并且可用于删除多个键(请参阅代码中的注释):

var obj = {
  total: 350,
  SN1: {
    reach: 200,
    engagementRate: 1.35,
    DEEP_SN1: {
      reach: 200,
      engagementRate: 1.35
    }
  },
  SN2: {
    reach: 150,
    engagementRate: 1.19
  }
};

function deepOmit(obj, keysToOmit) {
  var keysToOmitIndex =  _.keyBy(Array.isArray(keysToOmit) ? keysToOmit : [keysToOmit] ); // create an index object of the keys that should be omitted

  function omitFromObject(obj) { // the inner function which will be called recursivley
    return _.transform(obj, function(result, value, key) { // transform to a new object
      if (key in keysToOmitIndex) { // if the key is in the index skip it
        return;
      }

      result[key] = _.isObject(value) ? omitFromObject(value) : value; // if the key is an object run it through the inner function - omitFromObject
    })
  }
  
  return omitFromObject(obj); // return the inner function result
}

console.log(deepOmit(obj, 'reach')); // you can use a string for a single value

console.log(deepOmit(obj, ['reach', 'engagementRate'])); // you can use an array of strings for multiple values
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

我接受这个答案,因为它更完整,即使 @Tholle 答案在更简单的情况下也有效。
2021-05-14 08:09:12

似乎没有深度omit,但您可以遍历对象中的所有键,并reach递归地从嵌套对象中删除

function omitDeep(obj) {
  _.forIn(obj, function(value, key) {
    if (_.isObject(value)) {
      omitDeep(value);
    } else if (key === 'reach') {
      delete obj[key];
    }
  });
}

_.mapValues(object, v => _.isObject(v)? _.omit(v, 'reach'): v)

_.mapValues(object, [iteratee=_.identity])

创建一个对象,其键与 object 和通过运行objectthru 的 每个自己的可枚举字符串键控属性生成的值相同iteratee迭代器使用三个参数调用:(valuekeyobject)。

_.omit(object, [props])

创建一个由自己的和继承的可枚举字符串键控属性组成的对象,这些属性object未被省略。

使用_.mixin扩展 omitDeep 方法:

_.mixin({
    'omitDeep': function(obj, predicate) {
        return _.transform(obj, function(result, value, key) {
            if (_.isObject(value)) {
                value = _.omitDeep(value, predicate);
            }
            var doOmit = predicate(value, key);
            if (!doOmit) {
                _.isArray(obj) ? result.push(value) : result[key] = value;
            }
        });
    }
});

var my = {
    "key1": {
        "key2": {
            "key3": [null, {
                "key4": "string",
                "key5": true,
                "key6": null,
                "key7": 8,
                "key7": undefined
            }, null]
        }
    }
};

console.log(my);
console.log("omit null:", _.omitDeep(my, _.isNull));
console.log("omit undefined:", _.omitDeep(my, _.isUndefined));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

通过在 ES6 + Typescript 中定义一组排除键,递归地省略对象中的键。

omitDeep(myObject, [omitKey1, omitKey2, ...omitKeyN])

// omitDeep.ts

/**
 * Recursively remove keys from an object
 * @usage
 *
 * const input = {
 *   id: 1,
 *   __typename: '123',
 *   createdAt: '1020209',
 *   address: {
 *     id: 1,
 *     __typename: '123',
 *   },
 *   variants: [
 *     20,
 *     {
 *       id: 22,
 *       title: 'hello world',
 *       __typename: '123',
 *       createdAt: '1020209',
 *       variantOption: {
 *         id: 1,
 *         __typename: '123',
 *       },
 *     },
 *     {
 *       id: 32,
 *       __typename: '123',
 *       createdAt: '1020209',
 *     },
 *   ],
 * }
 *
 * const output = {
 *   id: 1,
 *   address: {
 *     id: 1,
 *   },
 *   variants: [
 *     20,
 *     {
 *       id: 22,
 *       title: 'hello world',
 *       variantOption: {
 *         id: 1,
 *       },
 *     },
 *     {
 *       id: 32,
 *     },
 *   ],
 * }
 *
 * expect(omitDeep(input, ['createdAt, 'updatedAt', __typename']).to.deep.equal(output) // true
 *
 * @param {object} input
 * @param {Array<number | string>>} excludes
 * @return {object}
 */
const omitDeep = (input: object, excludes: Array<number | string>): object => {
  return Object.entries(input).reduce((nextInput, [key, value]) => {
    const shouldExclude = excludes.includes(key)
    if (shouldExclude) return nextInput

    if (Array.isArray(value)) {
      const arrValue = value
      const nextValue = arrValue.map((arrItem) => {
        if (typeof arrItem === 'object') {
          return omitDeep(arrItem, excludes)
        }
        return arrItem
      })
      nextInput[key] = nextValue
      return nextInput
    } else if (typeof value === 'object') {
      nextInput[key] = omitDeep(value, excludes)
      return nextInput
    }

    nextInput[key] = value

    return nextInput
  }, {})
}

export default omitDeep