移除 JSON 对象中的数字值

问题描述

给定一个符合 JSON 格式的对象或数组 obj,返回一个不包含数字值的新对象或数组。

这个新对象/数组与原始结构相同,但移除了所有值为 number 类型的键值对。这个操作需要递归地应用于所有嵌套的对象和数组。

注意:

  • 数组被视为其索引是键的特殊对象。
  • 完全由数字组成的字符串(例如 "123"不属于数字类型,应当被保留。
  • nullundefined 值也应该被保留。

示例

示例 1:

  • 输入: obj = [null, 0, false, 1, "2"]
  • 说明: 移除了索引 1 (值为 0) 和索引 3 (值为 1)。
  • 输出: [null, false, "2"]

示例 2:

  • 输入: obj = {"a": 1, "b": [false, 1, "2"]}
  • 说明: 移除了键 "a" (值为 1)。在嵌套数组中,移除了值为 1 的元素。
  • 输出: { "b": [false, "2"]}

示例 3:

  • 输入: obj = [null, "0", 5, [0], [false, 16]]
  • 说明: 移除了顶层的 5。在第一个嵌套数组 [0] 中移除了 0,使其变为空数组 []。在第二个嵌套数组 [false, 16] 中移除了 16
  • 输出: [null, "0", [], [false]]

解题思路

解决这个问题的核心是编写一个递归函数,该函数能够处理三种情况:数组、对象和基本类型值。

  1. 基本情况(递归出口): 如果传入的值不是对象(即是字符串、布尔值、nullundefined 或数字),则直接返回该值。过滤操作将在调用它的上一层级中处理。

  2. 处理数组: 如果传入的值是一个数组,我们创建一个新的空数组。然后遍历原数组的每一个元素,对每个元素进行递归调用。如果递归调用的返回值不是 number 类型,我们就将其添加到新数组中。

  3. 处理对象: 如果传入的值是一个普通对象,我们创建一个新的空对象。然后遍历原对象的每一个键。对于每个键,我们检查其对应的值。如果值是 number 类型,我们就忽略这个键值对。否则,我们对该值进行递归调用,并将返回的结果以相同的键存入新对象中。

这种方法确保了我们能深入到任意层级的嵌套结构中,并正确地移除所有值为数字类型的元素或属性。

代码实现

/**
 * 给定一个对象或数组 obj,它符合JSON的格式, 返回一个不包含数字值的对象。
 * 不包含数字值的对象与原始对象相同,只是将包含数字类型的值的键移除。
 * 该操作适用于对象及其嵌套对象。数组被视为索引作为键的对象。
 * @param {any} obj - JSON-like object or array
 * @returns {any} - a new object or array without numeric values
 */
function removeNumericValues(obj) {
  // 处理数组
  if (Array.isArray(obj)) {
    const newArr = [];
    for (const item of obj) {
      // 如果值是数字,则跳过
      if (typeof item === 'number') {
        continue;
      }
      // 递归处理数组中的每一项
      newArr.push(removeNumericValues(item));
    }
    return newArr;
  }

  // 处理对象 (但不是 null)
  if (typeof obj === 'object' && obj !== null) {
    const newObj = {};
    for (const key in obj) {
      const value = obj[key];
      // 如果值是数字,则跳过
      if (typeof value === 'number') {
        continue;
      }
      // 递归处理对象中的每一个值
      newObj[key] = removeNumericValues(value);
    }
    return newObj;
  }

  // 基本类型值直接返回
  return obj;
}

// --- 测试用例 ---

// 示例 1
const obj1 = [null, undefined, 0, false, 1, '2'];
const output1 = removeNumericValues(obj1);
console.log('示例 1 输入:', JSON.stringify(obj1));
console.log('示例 1 输出:', JSON.stringify(output1)); // 预期: [null,undefined,false,"2"]
console.log('\n');

// 示例 2
const obj2 = { a: 1, b: [false, 1, '2'] };
const output2 = removeNumericValues(obj2);
console.log('示例 2 输入:', JSON.stringify(obj2));
console.log('示例 2 输出:', JSON.stringify(output2)); // 预期: {"b":[false,"2"]}
console.log('\n');

// 示例 3
const obj3 = [null, '0', 5, [0], [false, 16]];
const output3 = removeNumericValues(obj3);
console.log('示例 3 输入:', JSON.stringify(obj3));
console.log('示例 3 输出:', JSON.stringify(output3)); // 预期: [null,"0",[],[false]]
console.log('\n');

// 更多测试用例
const obj4 = {
  id: 123,
  user: 'test',
  data: {
    score: 100,
    items: ['item1', 200, { rank: 1, valid: true }],
  },
  meta: null,
};
const output4 = removeNumericValues(obj4);
console.log('复杂对象输入:', JSON.stringify(obj4));
console.log('复杂对象输出:', JSON.stringify(output4)); // 预期: {"user":"test","data":{"items":["item1",{"valid":true}]},"meta":null}
Copyright © Jun 2025 all right reserved,powered by Gitbook该文件修订时间: 2025-07-03 17:35:08

results matching ""

    No results matching ""

    results matching ""

      No results matching ""