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
相关产品推荐
相关产品推荐

