Lodash递归删除项目

13

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

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

我一直在尝试迭代地使用remove()方法,但总是返回未定义的对象,所以我确信我的做法是错误的。而且这还是我第一次使用lodash,所以这可能是我的实际问题。

有人可以帮忙吗?

6个回答

21

_.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的答案在简单情况下也是有效的。 - Zed_Blade

6

似乎没有一个深度的omit,但是你可以迭代对象中的所有键,并递归地从嵌套对象中删除reach

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

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

function omitDeep(obj) {
  _.forIn(obj, function(value, key) {
    if (_.isObject(value)) {
      omitDeep(value);
    } else if (key === 'reach') {
      delete obj[key];
    }
  });
}
omitDeep(obj)
console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>


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

_.mapValues(对象, [迭代器=_.identity])

创建一个与对象相同的键,并通过将对象的每个可枚举字符串键属性运行到迭代器中生成值。迭代器使用三个参数调用:(对象)。

_.omit(对象, [属性])

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


2
使用_.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>


2

通过在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

0

我必须递归地从一个对象数组中删除两个键的所有出现。omit-deep-lodash库允许在一行代码中递归地省略对象键和值。可以在一次调用中删除多个键。对于那些觉得delete太可变的人来说,这是一个功能性的解决方案。请务必阅读此处的注释。omit-deep-lodash

const omitDeep = require("omit-deep-lodash");
 
omitDeep({a: "a", b: "b", c: {b: "b", d: {b: "b", f: "f"}}}, "b");
//=> {a: "a", c: {d: {f: "f"}}}
 
omitDeep({a: "a", b: "b", c: {b: "b", d: {b: "b", f: "f"}}}, "a", "b");


给未来的读者添加一些关于这个库的描述可能会更有帮助。 - Mechanic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接