динамически сглаженный вложенный массив объектов javascript - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь написать функцию, которая будет принимать массив вложенных объектов и динамически возвращать плоский результат. arrayProperties.filter() не возвращает массив объектов, как я ожидал.

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"
    }
]

Ответы [ 4 ]

1 голос
/ 31 марта 2020

Вы можете использовать рекурсию, чтобы сгладить объекты в объект одного уровня и передать эту функцию на карту, чтобы получить массив сплющенного объекта

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)))
1 голос
/ 31 марта 2020

Вы можете использовать map, который вернет массив и рекурсивную функцию. Добавили комментарий в код, надеюсь, это будет полезно

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)
1 голос
/ 31 марта 2020

Вы можете использовать свойство объекта l oop, используя ключевое слово 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);

Вам нужно обработать дубликаты

0 голосов
/ 31 марта 2020

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 l oop, каждая запись может быть деструктурирована:

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

  1. Объявить пустой массив и выполнить итерацию по каждому литералу объекта в массиве объектов:

    let array = [];
    for (let obj of objArray) {...
    
  2. Для каждого объекта объявите пустой объект и затем преобразуйте каждый ключ / значение каждого объекта в подмассив:

    let object = {};
    for (let [key, value] of Object.entries(obj)) {...
    
  3. Проверьте каждое значение каждого литерала объекта - если значение является литералом объекта ...

    if (Object.prototype.toString.call(value) == "[object Object]") {...
    
  4. ... итерация по значению и назначение каждого ключа / значения пустому объекту .. .

    for (let [k, v] of Object.entries(value)) {
      object[k] = v;
    }
    
  5. ... в противном случае присвойте ключ / значение пустому объекту ...

    } else {
      object[key] = value;
    }
    
  6. Pu sh новый объект для нового массива:

    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));
...