递归对象转换 JS 实用程序 - 但是嵌套值可能是

Recurisve Object Transformation JS Utility - however nested values might be

提问人:Ashish dahiya 提问时间:10/9/2023 最后编辑:Abito PrakashAshish dahiya 更新时间:10/10/2023 访问量:64

问:

我希望制作一个实用函数 - 它接受输入 - vanilla plain 对象 - 这样 - 它递归地遍历它到最深的层次,即使一个值是一个数组,它也应该遍历它的各个元素,并且对于每个数组值的元素或字段的值 - 它检查 -

  1. 如果当前迭代的值为 nullish(null 或 undefined) - 它将值 “NULL_VALUE” 设置为字符串,
  2. 如果当前迭代的值为空字符串 (“”),则它将值 “EMPTY_VALUE” 设置为字符串,
  3. 如果当前迭代的值为空数组 ( [] ),则它将值 “EMPTY_ARRAY” 设置为字符串,
  4. 如果当前迭代的值是对象数组 ( { } ),则它将值 “EMPTY_OBJECT” 设置为字符串,
  5. 最后,如果它的任何值不是上面的值,则该值将作为字符串“VALID_VALUE”

const input = {
  a: null,
  b: "",
  c: [],
  d: {},
  e: "hello",
  f: [null, "", [], {}, "world"],
  g: {
    h: null,
    i: "",
    j: [],
    k: {},
    l: "nested",
  },
};

输出

{
  a: "NULL_VALUE",
  b: "EMPTY_VALUE",
  c: "EMPTY_ARRAY",
  d: "EMPTY_OBJECT",
  e: "VALID_VALUE",
  f: ["NULL_VALUE", "EMPTY_VALUE", "EMPTY_ARRAY", "EMPTY_OBJECT", "VALID_VALUE"],
  g: {
    h: "NULL_VALUE",
    i: "EMPTY_VALUE",
    j: "EMPTY_ARRAY",
    k: "EMPTY_OBJECT",
    l: "VALID_VALUE",
  },
}

我目前的方法如下,对于非常嵌套的对象,它不能完全按预期工作,因为跳过了一些空数组和对象

const transformObject = (obj) => {
    const transformedObj = {};
    for (const key in obj) {
        const value = obj[key];
        if (Array.isArray(value)) {
            transformedObj[key] = transformValue(transformArray(value));
        } else if (isPlainObject(value)) {
            transformedObj[key] = transformValue(transformObject(value));
        } else {
            transformedObj[key] = transformValue(value);
        }
    }
    return transformedObj;
};

const transformArray = (arr: any[]): any[] => {
    return arr.map((item) => {
        if (isPlainObject(item)) return transformObject(item);
        if (Array.isArray(item)) return transformArray(item);
        return transformValue(item);
    });
};

const transformValue = (value: any): any => {
    if (value === null || value === undefined) return "NULL_VALUE";
    if (value === "") return "EMPTY_VALUE";
    if (Array.isArray(value) && value.length === 0) return "EMPTY_ARRAY";
    if (isPlainObject(value) && Object.keys(value).length === 0)
        return "EMPTY_OBJECT";
    return value;
};
JavaScript 数组 JSON 对象 递归

评论


答:

1赞 Abito Prakash 10/9/2023 #1

下面是一个类似的递归方法

const input = {a:null,b:"",c:[],d:{},e:"hello",f:[null,"",[],{},"world"],g:{h:null,i:"",j:[],k:{},l:"nested"}};

const transformObject = (obj) => {
  if (obj === undefined || obj === null) return "NULL_VALUE";

  if (obj === "") return "EMPTY_VALUE";

  if (Array.isArray(obj))
    return obj.length ? obj.map(transformObject) : "EMPTY_ARRAY";

  if (typeof obj === "object") {
    const entries = Object.entries(obj);

    return entries.length ?
      entries.reduce((acc, [key, value]) => {
        acc[key] = transformObject(value);
        return acc;
      }, {}) :
      "EMPTY_OBJECT";
  }

  return "VALID_VALUE";
};

console.log(transformObject(input))

1赞 Mulan 10/10/2023 #2

这里有一些函数,将输入映射到所需的输出 -Ft

const F = (t) => {
  switch (t?.constructor) {
    case Object:
      const keys = Object.keys(t)
      if (keys.length == 0) return "EMPTY_OBJECT"
      return Object.fromEntries(keys.map(k => [k, F(t[k])]))
    case Array:
      if (t.length == 0) return "EMPTY_ARRAY"
      return t.map((v, k) => F(v))
    case String:
      if (t == "") return "EMPTY_VALUE"
      break
    case undefined:
      return "NULL_VALUE"
  }
  return "VALID_VALUE"
}

console.log(F({a:null,b:"",c:[],d:{},e:"hello",f:[null,"",[],{},"world"],g:{h:null,i:"",j:[],k:{},l:"nested"},}))

这是一个添加了输入和输出类型的 TypeScript 版本 -IO

type I = null | string | Array<I> | { [key: string]: I }

type O =
  | "NULL_VALUE"
  | "EMPTY_VALUE"
  | "EMPTY_ARRAY"
  | "EMPTY_OBJECT"
  | "VALID_VALUE"
  | Array<O>
  | { [key: string]: O }

const F = (t: I): O => {
  switch (t?.constructor) {
    case Object: {
      const keys = Object.keys(t)
      if (keys.length == 0) return "EMPTY_OBJECT"
      return Object.fromEntries(keys.map(k => [k, F(t[k])]))
    }
    case Array: {
      if (t.length == 0) return "EMPTY_ARRAY"
      return (t as Array<I>).map((v, k) => F(v))
    }
    case String: {
      if (t == "") return "EMPTY_VALUE"
      break
    }
    case undefined: {
      return "NULL_VALUE"
    }
  }
  return "VALID_VALUE"
}