如何使用lodash从对象中删除空值

问题描述 投票:0回答:7

我有一个具有多个属性的对象,我想使用 lodash 删除空的对象/嵌套对象。最好的方法是什么?

Let template = {
      node: "test",
      representation: {
        range: { }
      },
      transmit: {
        timeMs: 0
      }
    };

template = {
      node: "test",
      transmit: {
        timeMs: 0
      }
    };

我尝试过类似的事情,但我迷路了。

Utils.removeEmptyObjects = function(obj) {
  return _.transform(obj, function(o, v, k) {
    if (typeof v === 'object') {
      o[k] = _.removeEmptyObjects(v);
    } else if (!_.isEmpty(v)) {
      o[k] = v;
    }
  });
};
_.mixin({
  'removeEmptyObjects': Utils.removeEmptyObjects
});
javascript object lodash
7个回答
18
投票

您可以通过几个步骤来实现这一点:

  1. 使用 pickBy() 使用 isObject() 谓词来选取对象键值。

  2. 使用 mapValues() 递归调用

    removeEmptyObjects()
    ,注意它只会用对象调用此函数。

  3. 使用

    omitBy()
    isEmpty() 谓词删除在 mapValues() 之后找到的所有空对象。

  4. 使用 assign() 重新分配对象中的所有原始值,并使用

    omitBy()
    谓词进行
    isObject()


function removeEmptyObjects(obj) {
  return _(obj)
    .pickBy(_.isObject) // pick objects only
    .mapValues(removeEmptyObjects) // call only for object values
    .omitBy(_.isEmpty) // remove all empty objects
    .assign(_.omitBy(obj, _.isObject)) // assign back primitive values
    .value();
}

function removeEmptyObjects(obj) {
  return _(obj)
    .pickBy(_.isObject)
    .mapValues(removeEmptyObjects)
    .omitBy(_.isEmpty)
    .assign(_.omitBy(obj, _.isObject))
    .value();
}

_.mixin({
  removeEmptyObjects: removeEmptyObjects
});

var template = {
  node: "test",
  representation: {
    range: {}
  },
  transmit: {
    timeMs: 0
  }
};

var result = _.removeEmptyObjects(template);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>


9
投票

从没有嵌套对象的对象中删除未定义、null 和空字符串

_.omitBy(object, (v) => _.isUndefined(v) || _.isNull(v) || v === '');

对于嵌套对象,您可以使用递归函数来实现

它将删除任何级别的空对象、空数组、null、未定义、空字符串...

removeEmpty(obj) {
        let finalObj = {};
        Object.keys(obj).forEach((key) => {
            if (obj[key] && typeof obj[key] === 'object') {
                const nestedObj = removeEmpty(obj[key]);
                if (Object.keys(nestedObj).length) {
                    finalObj[key] = nestedObj;
                }
            } else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
                finalObj[key] = obj[key];
            }
        });
        return finalObj;
    }



更新2022年4月11日

根据@RahulSoni 评论,我刚刚修复了数组到对象的转换。现在一切都该处理了。如果您还有其他意见请告诉我

removeEmpty(obj) {
    const finalObj = {};
    Object.keys(obj).forEach((key) => {
      if (obj[key] && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
        const nestedObj = this.removeEmpty(obj[key]);
        if (Object.keys(nestedObj).length) {
          finalObj[key] = nestedObj;
        }
      } else if (Array.isArray(obj[key])) {
        if (obj[key].length) {
          obj[key].forEach((x) => {
            const nestedObj = this.removeEmpty(x);
            if (Object.keys(nestedObj).length) {
              finalObj[key] = finalObj[key] ? [...finalObj[key], nestedObj] : [nestedObj];
            }
          });
        }
      } else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
        finalObj[key] = obj[key];
      }
    });
    return finalObj;
  }

示例:

   const obj = {
            a: '',
            aa: null,
            aaa: undefined,
            aaaa: 'aaaa',
            aaaaa: 0,
            aaaaaa: 1,
            aaaaaaa: 2,
            aaaaaaaa: true,
            aaaaaaaaa: false,
            emptyObj: {},
            emptyArray: [],
            array: [
                {
                    a: '',
                    aa: null,
                    aaa: undefined,
                    aaaa: 'aaaa',
                    aaaaa: 0,
                    aaaaaa: 1,
                    aaaaaaa: 2,
                    aaaaaaaa: true,
                    aaaaaaaaa: false,
                    emptyObj: {},
                    emptyArray: [],
                    obj: {
                        a: '',
                        aa: null,
                        aaa: undefined,
                        aaaa: 'aaaa',
                        aaaaa: 0,
                        aaaaaa: 1,
                        aaaaaaa: 2,
                        aaaaaaaa: true,
                        aaaaaaaaa: false,
                        emptyObj: {},
                        emptyArray: [],
                    },
                },
                {
                    a: '',
                    aa: null,
                    aaa: undefined,
                    aaaa: 'aaaa',
                    aaaaa: 0,
                    aaaaaa: 1,
                    aaaaaaa: 2,
                    aaaaaaaa: true,
                    aaaaaaaaa: false,
                    emptyObj: {},
                    emptyArray: [],
                    obj: {
                        a: '',
                        aa: null,
                        aaa: undefined,
                        aaaa: 'aaaa',
                        aaaaa: 0,
                        aaaaaa: 1,
                        aaaaaaa: 2,
                        aaaaaaaa: true,
                        aaaaaaaaa: false,
                        emptyObj: {},
                        emptyArray: [],
                    },
                },
            ],
            b: {
                a: '',
                aa: null,
                aaa: undefined,
                aaaa: 'aaaa',
                aaaaa: 0,
                aaaaaa: 1,
                aaaaaaa: 2,
                aaaaaaaa: true,
                aaaaaaaaa: false,
                emptyObj: {},
                emptyArray: [],
                c: {
                    a: '',
                    aa: null,
                    aaa: undefined,
                    aaaa: 'aaaa',
                    aaaaa: 0,
                    aaaaaa: 1,
                    aaaaaaa: 2,
                    aaaaaaaa: true,
                    aaaaaaaaa: false,
                    emptyObj: {},
                    emptyArray: [],
                },
            },
        };

        const finalObj = removeEmpty(obj);
        console.log('finalObj After remove', finalObj);

1
投票

这个(打字稿)也适用于数组并支持摇树:

import flow from "lodash/fp/flow";
import pickBy from "lodash/fp/pickBy";
import mapValues from "lodash/fp/mapValues";
import map from "lodash/fp/map";
import assign from "lodash/fp/assign";
import { default as fpOmitBy } from "lodash/fp/omitBy";
import { default as fpFilter } from "lodash/fp/filter";
import { isArray, isEmpty, isObject, omitBy } from "lodash-es";

export const compact = (obj) => !isObject(obj) ? obj : isArray(obj) ? compactArray(obj) : compactObject(obj);

const compactArray = (arr) => flow(
  map(compact),
  fpFilter(x => !isEmpty(x) || !isObject(x)),
)(arr)

const compactObject = (obj) =>  flow(
  pickBy(isObject),
  mapValues(compact), 
  fpOmitBy(isEmpty),
  assign(omitBy(obj, isObject)),
)(obj);

0
投票

这是 Amr 函数的修改版本,它解决了我遇到的问题,它提供如下输入:

const data = {
                    key1: 'value1',
                    topLevelKey1: {
                    key2: {}
                    },
                    key3: 'value3',
                    updates: [
                    { toDeleteKey: {}, fullKey: 'has a value' },
                    { toDeleteKey2: {}, fullKey2: 'has a value',
                    media: [
                        "https://thisisalink.com",
                        "https://thisisanotherlink.com",
                      ]},
                    ],
                };

它将像对象一样对待媒体中的字符串并将它们分开:

"media":[{"0":"h","1":"t","2":"t","3":"p","4":"s"...
function removeEmpty(obj: Record<string, any>): Record<string, any> {
    const finalObj: Record<string, any> = {};
    Object.keys(obj).forEach((key) => {
      if (obj[key] && typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
        const nestedObj = removeEmpty(obj[key]);
        if (Object.keys(nestedObj).length) {
          finalObj[key] = nestedObj;
        }
      } else if (Array.isArray(obj[key])) {
        if (obj[key].length) {
          finalObj[key] = obj[key].map((x) => {
            if (typeof x === 'object' && !Array.isArray(x)) {
              return removeEmpty(x);
            } else {
              return x;
            }
          });
        }
      } else if (obj[key] !== '' && obj[key] !== undefined && obj[key] !== null) {
        finalObj[key] = obj[key];
      }
    });
    return finalObj;
  }

0
投票

使用 fp 的更简单方法可能是:

const removeEmptyProperties = fp.omitBy(fp.isEmpty);
const compactObject = (obj: unknown) => {
  return fp.mapValues((value: unknown) => {
    if (fp.isObject(value)) {
      return removeEmptyProperties(compactObject(value));
    }

    return value;
  })(obj);
};

-1
投票

我正在为那些将来寻找此问题解决方案的人更新此内容。

lodash 提供了一种更简单的方法来做到这一点。

_.compact(arrayName) 将使用 lodash 从数组中删除所有空/未定义/空值


-3
投票

您可以使用

_.pick
仅选择您想要的属性,如

var desiredTemplate = _.pick(template, ['node','transmit']); 

否则,据我所知,lodash 没有任何内置功能可以从对象中递归删除空对象/数组。

© www.soinside.com 2019 - 2025. All rights reserved.