You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ramda:如何递归移除对象中值为null、空数组及空列表的键?

递归移除对象/数组中的Null值(Ramda实现)

没问题,我来帮你搞定这个递归清理null值的需求!你的原代码只能处理顶层对象的null键,没法深入嵌套结构和数组,而且也没处理清理后变成空的对象/数组——刚好这正是你测试用例里需要的效果。

解决方案:递归深度清理函数

我们可以用Ramda的cond来做类型分支判断,分别处理数组、对象和其他类型的值,实现深度递归的清理:

import R from 'ramda';

const removeNullsDeep = R.cond([
  // 处理数组:递归清理每个元素,再过滤掉空的容器(空对象/数组)
  [R.is(Array), R.pipe(
    R.map(removeNullsDeep),
    R.reject(R.either(R.isEmpty, R.isNil))
  )],
  // 处理对象:递归清理每个值,先移除null值的键,再移除空对象
  [R.is(Object), R.pipe(
    R.map(removeNullsDeep),
    R.reject(R.equals(null)),
    R.reject(R.isEmpty)
  )],
  // 非对象/数组类型直接返回(保留空字符串、0、false等合法值)
  [R.T, R.identity]
]);

逻辑说明

  • 数组处理:先对数组每个元素递归执行清理,然后把那些处理后变成空的元素(比如{nool: null}清理后是空对象,或者空数组)过滤掉,这样你的uselessArray就会被完全移除。
  • 对象处理:先递归清理对象的每个值,然后移除值为null的键,最后如果对象清理后变成空(比如你的useless对象),就把整个对象键也移除。
  • 基础类型保留:空字符串''、数字0、布尔值false这些都不会被清理,完美匹配你提到的AJV/JSON Schema中null !== undefined的特性需求。

测试验证

把这个函数替换到你的测试用例里,就能得到预期结果:

describe('filter null values recursively', () => {
  it('should filter out null values deeply', () => {
    const specimen = {
      tasks: [
        { id: 'foo', blank: '', zero: 0, nool: null },
        { nool: null },
        { id: '', blank: null, zero: 0, nool: null },
      ],
      useless: { nool: null },
      uselessArray: [{ nool: null }],
      nool: null,
    };
    const expectation = {
      tasks: [
        { id: 'foo', blank: '', zero: 0 },
        { id: '', zero: 0 },
      ],
    };
    expect(removeNullsDeep(specimen)).toEqual(expectation);
  });
});

可选调整

如果你不想移除清理后的空对象/数组,只需要去掉对应的R.reject(R.isEmpty)即可:

  • 数组部分去掉R.reject(R.isEmpty),会保留空数组
  • 对象部分去掉R.reject(R.isEmpty),会保留空对象

内容的提问来源于stack exchange,提问作者Archimedes Trajano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:02:37