Как глубоко удалить нулевые значения, пустые объекты и пустой массив из объекта - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть объект, который выглядит так:

var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] }

Я хочу удалить пустые значения и пустые объекты (массивы и объекты), чтобы они выглядели так:

{ a: {c: [ {d: 2} ], e: 2 }, i: [ 2 ] }

Функция должна удалять нулевые значения, пустые объекты и пустые массивы. Какой-нибудь элегантный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Чтобы уменьшить количество повторяющихся кодов, одним из вариантов является определение функции (назовем ее itemToBool), которая может определить, является ли переданное ему универсальное значение достоверным или рекурсивно истинным где-то , если значение быть массивом или объектом. Затем в функции, которая получает исходный объект (или рекурсивно передает объект или массив), вы можете вызывать эту функцию itemToBool всякий раз, когда есть значение для проверки.

В случае массивов map на itemToBool, а затем filter на логическое значение. В случае объектов reduce entries объекта в другой объект: передайте каждое значение объекта через itemToBool, чтобы рекурсивно преобразовать его (в случае, если значение является массивом или объектом), и если преобразованный Значение имеет любые ключи (или является истинным примитивом), присваивает его аккумулятору. Не нужно зависеть от библиотеки:

var myObject = {
  a: {
    b: [{}],
    c: [{}, {
      d: 2
    }],
    e: 2,
    f: {}
  },
  g: {},
  h: [],
  i: [null, 2]
};

// Returns a falsey value if the item is falsey,
// or if the deep cleaned array or object is empty:
const itemToBool = item => {
  if (typeof item !== 'object' || item === null) return item;
  const cleanedItem = clean(item);
  return Object.keys(cleanedItem).length !== 0 && cleanedItem;
};

const clean = obj => {
  if (Array.isArray(obj)) {
    const newArr = obj.map(itemToBool).filter(Boolean);
    return newArr.length && newArr;
  }
  const newObj = Object.entries(obj).reduce((a, [key, val]) => {
    const newVal = itemToBool(val);
    if (newVal) a[key] = newVal;
    return a;
  }, {});
  return Object.keys(newObj).length > 0 && newObj;
};

console.log(clean(myObject));

Хм ... вы также можете абстрагировать проверку количества клавиш в функции:

var myObject={a:{b:[{}],c:[{},{d:2}],e:2,f:{}},g:{},h:[],i:[null,2]}

// Returns the object / array if it has at least one key, else returns false:
const validObj = obj => Object.keys(obj).length && obj;
const itemToBool = item => (
  typeof item !== 'object' || item === null
  ? item
  : validObj(clean(item))
);
const clean = obj => validObj(
  Array.isArray(obj)
  ? obj.map(itemToBool).filter(Boolean)
  : Object.entries(obj).reduce((a, [key, val]) => {
      const newVal = itemToBool(val);
      if (newVal) a[key] = newVal;
      return a;
    }, {})
);

console.log(clean(myObject));
0 голосов
/ 05 сентября 2018

Мы не знаем, что вы подразумеваете под clean , но из того, что я понимаю, вы хотите удалить все нулевые и пустые значения. Этот алгоритм прост: рекурсивно проверяет и удаляет все пустые / нулевые значения (которые рекурсивно проверяются).

function clean(obj) {
  // clean array
  if (Array.isArray(obj)) {
    for (let i=0; i<obj.length; i++) {
      if (isNothing(obj[i])) obj.splice(i, 1);  // remove value if falsy
      else if (typeof obj[i] === 'object') clean(obj[i]); // recurse if it's a truthy object
    }
    
  // clean other object
  } else {
    for (let prop in obj) {
      if (!obj.hasOwnProperty(prop)) continue;
      if (isNothing(obj[prop])) delete obj[prop]; // remove value if falsy
      else if (typeof obj[prop] === 'object') clean(obj[prop]); // recurse if it's a truthy object
    }
  }
}

// Recursively check for populated or nonnull content. If none found, return `true`. Recursive so [{}] will be treated as empty.
function isNothing(item) {
  // null / undefined
  if (item == null) return true;
  
  // deep object falsiness
  if (typeof item === 'object') {
    if (Array.isArray(item)) {
      // array -> check for populated/nonnull value
      for (let i=0; i<item.length; i++) {
        if (!isNothing(item[i])) return false;
      }
      return true;
    }
    // other object -> check for populated/nonnull value
    for (let prop in item) {
      if (!item.hasOwnProperty(prop)) continue;
      if (!isNothing(item[prop])) return false;
    }
    return true;
  }
  return false;
}

var myObject = { a: { b: [{}], c: [{}, {d: 2}], e: 2, f: {} }, g:{}, h:[], i: [null, 2] };

console.log("Before: " + JSON.stringify(myObject));
clean(myObject);
console.log("After: " + JSON.stringify(myObject));
0 голосов
/ 05 сентября 2018

Вот функция, которая рекурсивно очищает объект. Он будет проходить через все свойства и удалять нулевые значения, нулевые массивы и нулевые объекты:

cleanUpObject(jsonObject: object): object {

    Object.keys(jsonObject).forEach(function (key, index) {
        const currentObj = jsonObject[key]

        if (_.isNull(currentObj)) {
            delete jsonObject[key]
        } else if (_.isObject(currentObj)) {
            if (_.isArray(currentObj)) {
                if (!currentObj.length) {
                    delete jsonObject[key]
                } else {
                    const cleanupArrayObj = []
                    for (const obj of currentObj) {
                        if (!_.isNull(obj)) {
                            const cleanObj = this.cleanUpJson(obj)
                            if (!_.isEmpty(cleanObj)) {
                                cleanupArrayObj.push(cleanObj)
                            }
                        }
                    }
                    if (!cleanupArrayObj.length) {
                        delete jsonObject[key]
                    } else {
                        jsonObject[key] = cleanupArrayObj
                    }
                }
            } else {
                if (_.isEmpty(Object.keys(jsonObject[key]))) {
                    delete jsonObject[key]
                } else {
                    jsonObject[key] = this.cleanUpJson(currentObj)

                    if (_.isEmpty(Object.keys(jsonObject[key]))) {
                        delete jsonObject[key]
                    }
                }
            }
        }
    }, this)

    return jsonObject
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...