动态展平嵌套对象数组 javascript

dynamically flatten nested array of objects javascript

我正在尝试编写一个函数来接受嵌套对象数组,并动态地 return 扁平化结果。 arrayProperties.filter() 并不是像我期望的那样 return 对象数组。

const data = [ 
    {
        parKeyA: "parValA",
        parKeyA1:
            {chiKeyA1: "chiValA1", chiKeyA2: "chiValA2"},
        parKeyA2: {chiKeyA3: "chiValA3"}
    },
    {
        parKeyB: "parValB",
        parKeyB1:
            {chiKeyB1:"chiValB1"}
    }
]

flatData = flatNestedObjArray(data);
console.log(flatData);

function flatNestedObjArray(array) {
    let flatArray = array.map(element => {
        let arrayProperties = Object.entries(element);
        //filter not returning array of objects
        let nestedObjects = arrayProperties.filter(property => {
            const parentValue = property[1];
            if (typeof parentValue === "object" && parentValue !== null) {
                return parentValue;
            }
        });
        //nestedObjects should be array of objects
        let merged = nestedObjects.map(obj => element.concat(obj));
        return merged;
    });
    return flatArray;
}

预期结果:

const data = [ 
    {
        parKeyA: "parValA",
        chiKeyA1: "chiValA1",
        chiKeyA2: "chiValA2",
        chiKeyA2: "chiValA2"
    },
    {
        parKeyB: "parValB",
        chiKeyB1:"chiValB1"
    }
]

您可以使用对象 属性 循环,使用 in 关键字为每个级别使用递归

for(var prop in data) {
    ....
}

我使用了一种旧的递归技术从一个工作代码开始

function flatten(data) {
    var newData = {};
    for(var prop in data) {
        if(typeof data[prop] == "object") {
            var childs = flatten(data[prop])
            for(var cprop in childs){
                newData[cprop] = childs[cprop];
            }
        }else {
            newData[prop] = data[prop]
        }
    }
    return newData;
}

for(var i=0;i<data.length;i++)
   data[i] = flatten(data[i]);

console.log(data);

您需要处理重复项

您可以使用递归将对象展平为单级对象,并将该函数传递给 map 以获得展平对象数组

const data = [{
    parKeyA: "parValA",
    parKeyA1: {
      chiKeyA1: "chiValA1",
      chiKeyA2: "chiValA2"
    },
    parKeyA2: {
      chiKeyA3: "chiValA3"
    }
  },
  {
    parKeyB: "parValB",
    parKeyB1: {
      chiKeyB1: "chiValB1",
      chiKeyB2: {}
    }
  }
]


let flatten = (obj, final = {}) => {
  for (let key in obj) {
    if (typeof obj[key] === 'object' && obj[key] != null) {
      flatten(obj[key], final)
    } else {
      final[key] = obj[key]
    }
  }
  return final
}

console.log(data.map((v) => flatten(v)))

您可以使用 map 这将 return 一个数组和一个递归函数。已在代码中添加注释,希望有用

const data = [{
    parKeyA: "parValA",
    parKeyA1: {
      chiKeyA1: "chiValA1",
      chiKeyA2: "chiValA2"
    },
    parKeyA2: {
      chiKeyA3: "chiValA2"
    }
  },
  {
    parKeyB: "parValB",
    parKeyB1: {
      chiKeyB1: "chiValB1"
    }
  }
]
/* Recursive function.It will take a object,iterate the object and check if the value of the key is another object. If it is another object then call same recursive function  */
function getFlatObj(obj) {
  let newObject = {}

  function doRecurssion(currObj) {
    // iterate through the object
    for (let keys in currObj) {
      // check if the value is another object 
      if (typeof currObj[keys] === 'object' && typeof currObj[keys] !== null) {
        doRecurssion(currObj)
      } else {
        // if not another object then add key and value
        newObject[keys] = currObj[keys]

      }
    }
    return newObject;
  }

  return doRecurssion(obj);
}

let flatObj = data.map((item) => {
  const acc = {};
  for (let keys in item) {
    if (typeof item[keys] === 'object' && typeof item[keys] !== null) {
      Object.assign(acc, getFlatObj(item[keys]))
    } else {
      acc[keys] = item[keys]
    }
  }

  return acc;
}, {});

console.log(flatObj)

Object.entries() 获取一个对象并将其转换为二维数组:

let object = {keyA: "valueA", keyB: "valueB", keyC: {kA: "vA", kB: "vB"}};
let array = Object.entries(object);
// array = [["keyA", "valueA"], ["keyB", "valueB"], ["keyC", {kA: "vA", kB: "vB"}]];

for...of 循环中使用上面的代码,每个条目都可以被解构:

for (let [key, value] of Object.entries(object)) {...

  1. 声明一个空数组并遍历对象数组中的每个对象文字:

    let array = [];
    for (let obj of objArray) {...
    
  2. 在每个对象上,声明一个空对象,然后将每个对象的每个key/value转换成一个子数组:

    let object = {};
    for (let [key, value] of Object.entries(obj)) {...
    
  3. 检查每个对象字面量的每个值——如果该值是对象字面量...

    if (Object.prototype.toString.call(value) == "[object Object]") {...
    
  4. ...遍历值并将每个 key/value 分配给空对象...

    for (let [k, v] of Object.entries(value)) {
      object[k] = v;
    }
    
  5. ...否则将key/value分配给空对象...

    } else {
      object[key] = value;
    }
    
  6. 将新对象推入新数组:

    array.push(object);
    

演示

const data = [{
    parKeyA: "parValA",
    parKeyA1: {
      chiKeyA1: "chiValA1",
      chiKeyA2: "chiValA2"
    },
    parKeyA2: {
      chiKeyA3: "chiValA3"
    }
  },
  {
    parKeyB: "parValB",
    parKeyB1: {
      chiKeyB1: "chiValB1"
    }
  }
];

function subObjToKeyVal(objArr) {
  let array = [];
  for (let obj of objArr) {
    let object = {};
    for (let [key, value] of Object.entries(obj)) {
      if (Object.prototype.toString.call(value) == "[object Object]") {
        for (let [k, v] of Object.entries(value)) {
          object[k] = v;
        }
      } else {
        object[key] = value;
      }
    }
    array.push(object);
  }
  return array;
}

console.log(subObjToKeyVal(data));