使用 Lodash 忽略嵌套属性

14

我正在尝试从以下对象中消除属性5MinuteRate15MinuteRate

var object = { requestsPerSecond:
   { mean: 1710.2180279856818,
     count: 10511,
     'currentRate': 1941.4893498239829,
     '1MinuteRate': 168.08263156623656,
     '5MinuteRate': 34.74630977619571,
     '15MinuteRate': 11.646507524106095 } };

Lodash的omit()函数似乎不能用于嵌套对象。以下代码无法工作:

console.log(_.omit(object, 'requestsPerSecond.count'));

编辑:

我尝试了这个,但它并不完全正确:

var subObject = _.omit(object.requestsPerSecond, '5MinuteRate', '15MinuteRate');

console.log(_.merge(object, subObject));

如果您只需要JSON,则可以将其与带有函数值的空壳合并,否则自定义map()回调和一对“delete”语句是最简单的选择。 - dandavis
我尝试了合并,但是我犯了一个错误。嵌套对象被合并到了顶层。你能看一下吗(在问题中)? - Hedge
7个回答

15
你已经接近成功了。只需要把你的subObject的结果赋给object.requestsPerSecond即可。

var object = {
  requestsPerSecond: {
    mean: 1710.2180279856818,
    count: 10511,
    'currentRate': 1941.4893498239829,
    '1MinuteRate': 168.08263156623656,
    '5MinuteRate': 34.74630977619571,
    '15MinuteRate': 11.646507524106095
  }
};

object.requestsPerSecond = _.omit(object.requestsPerSecond, '5MinuteRate', '15MinuteRate');

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


如果使用 _.omit,则会返回 object.requestsPerSecond 或 object。 - Yassine CHABLI
@MohammedYassineCHABLI _.omit 返回去除了指定属性的 requestsPerSecond 子对象。请注意,我将其设置回 object.requestsPerSecond 以覆盖先前的值。 - J. Titus

6

Lodash的_.omit函数适用于嵌套对象。看起来自您提出问题以来,该函数已经得到了改进 :)

object = _.omit(object, 'requestsPerSecond.5MinuteRate', 'requestsPerSecond.15MinuteRate');

更新

omit将在Lodash 5版本开始被移除。


1
看起来 Lodash v5 中将不会有 omit - Yuri Gor
这个真的有效吗?使用v 4.5.0 omit({ data: {a: 1, b: 2} }, 'data.a') == { data: { a: 1, b: 2 } } - Guillaume
这对于嵌套属性无效!请改用lodash的_.unset()方法!https://www.geeksforgeeks.org/lodash-_-unset-method/ - David
omitBy中似乎不可用。 - undefined

6
使用unset函数:https://lodash.com/docs#unset,可以使代码更加简洁。
var obj = { 
  requestsPerSecond: { 
    mean: 1710.2180279856818,
    count: 10511,
    'currentRate': 1941.4893498239829,
    '1MinuteRate': 168.08263156623656,
    '5MinuteRate': 34.74630977619571,
    '15MinuteRate': 11.646507524106095 
  } 
};

_.forEach(['requestsPerSecond.5MinuteRate', 'requestsPerSecond.15MinuteRate'], 
  function(omitProperty) {
    obj = _.unset(obj, omitProperty);
  }
);

// Or avoiding the "extra" loop.
obj = _.unset(obj, 'requestsPerSecond.5MinuteRate');
obj = _.unset(obj, 'requestsPerSecond.15MinuteRate');

感谢 @OscarRyz,我已经编辑了答案,使用 _.unset;我想我最初是考虑到了它,但打错了。 - aemonge

2
如果您需要深度省略某些路径,这里有一个来自Deepdash的omitDeep
obj = _.omitDeep(obj, /\.*5MinuteRate"\]$/);

请注意,此方法将排除所有匹配深度的路径。它支持单个路径或数组,表示为常量值或正则表达式。
对于作为参数给定的字符串路径,在对象中的每个路径都将被检查以结束给定条件。这里有一个更详细的 适用于你情况的codepen
(答案已更新以适应最新的Deepdash v3.1.0)

1

我曾经遇到过相同的问题,但它想要忽略嵌套对象中的所有具名属性。

这是一个通用函数,也适用于你的情况。

只需按照以下方式使用:omit(object, ['name_1', 'name_2, ...])

函数

// Variation on omit to recurse through objects and arrays
function omit(obj, arr) {
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (arr.includes(key)) {
        delete obj[key];
      } else if (Array.isArray(obj[key])) {
        for (let i = 0; i < obj[key].length; i++) {
          omit(obj[key][i], arr);
        }
      } else if (typeof obj[key] === 'object') {
        omit(obj[key], arr);
      }
    }
  }
  return obj;
}

var object = {
    requestsPerSecond: {
        mean: 1710.2180279856818,
        count: 10511,
        'currentRate': 1941.4893498239829,
        '1MinuteRate': 168.08263156623656,
        '5MinuteRate': 34.74630977619571,
        '15MinuteRate': 11.646507524106095
    }
};

object = omit(object, ['5MinuteRate','15MinuteRate']);
console.log(object);

你应该得到这样的结果

{
 "requestsPerSecond":
  {
    "mean": 1710.2180279856818,
    "count": 10511,
    "currentRate": 1941.4893498239828,
    "1MinuteRate": 168.08263156623656
  }
}

我本想使用更新的库,但由于我在Postman中运行测试用例,因此我的包和版本受到限制。


0

如果您愿意尝试另一个库,partial.lenses对集合的所有操作都有很好的支持,包括像对象的所有子项等复杂修改。

因此,在您的情况下,只需简单地使用以下代码即可(L只是从partial.lesnes导入的缩写):

const newObject = L.remove(['requestsPerSecond','5MinuteRate'],object)

现在想象一下,您有一个不同的结构,其中包含一组具有不同名称但具有相同结构的嵌套属性,并且您想要针对所有这些属性。想象一下这个例子:

obj = { 
  requestsPerSecond: {
  first: {
    mean: 1710.2180279856818,
    count: 10511,
    '5MinuteRate': 34.74630977619571,
    '15MinuteRate': 11.646507524106095 
  }}
  second: {
    mean: 1710.2180279856818,
    count: 10511,
    '5MinuteRate': 34.74630977619571,
    '15MinuteRate': 11.646507524106095 
  }} 
};

在这种情况下,它将会非常简单:
const newObject = L.remove(['requestsPerSecond',L.children,'5MinuteRate'],object)

L.children 意味着针对 requestPerSecond 的所有子元素进行操作。


0
如果你和我一样,正在尝试使用尚不支持嵌套过滤的omitBy函数,你可以使用以下代码。
const inputObject = {
  operation: "category",
  params: {
    city: undefined,
    location: {
      latitude: undefined,
      value: "not undefined"

    },
  },
  id: "test_id___20200101000000000",
  crawler: "crawler_id",
  queue: "task_queue",
  job: "crawler_id_scheduler_platform",
  seedId: "test_id",
};

function removeUndefined(obj) {
  return _.omitBy(obj, _.isUndefined);
}

function deepRemoveUndefined(obj) {
  if (_.isObject(obj)) {
    return removeUndefined(
      _.mapValues(obj, (val) => (val && _.isObject(val) ? deepRemoveUndefined(val) : val))
    );
  }
  return obj;
}

const cleanedObject = deepRemoveUndefined(inputObject);

console.log(cleanedObject);

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