如何在 Lodash 的 isEqualWith 中将缺失和未定义的属性视为等效属性

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

我正在与 Lodash 的

_.isEqualWith
的自定义比较功能进行斗争。我想要一个可以正常工作的函数:

const comparisonFunc = /* ...TBC... */

// Should be true:
_.isEqualWith({ a: undefined }, { }, comparisonFunc);

// Should still be false, as normal:
_.isEqualWith({ a: undefined }, { a: 123 }, comparisonFunc);

// Should still be false, as normal:
_.isEqualWith([undefined], [ ], comparisonFunc);

即对于比较中的任何对象(递归地),设置为

undefined
的属性应被视为不存在。

javascript lodash equality
5个回答
5
投票

这并不像我想要的那么简单,但我找到了解决方案:

const comparisonFunc = (a, b) => {
    if (_.isArray(a) || _.isArray(b)) return;
    if (!_.isObject(a) || !_.isObject(b)) return;

    if (!_.includes(a, undefined) && !_.includes(b, undefined)) return;

    // Call recursively, after filtering all undefined properties
    return _.isEqualWith(
        _.omitBy(a, (value) => value === undefined),
        _.omitBy(b, (value) => value === undefined),
        comparisonFunc
    );
}


// Should be true:
_.isEqualWith({ a: undefined }, { }, comparisonFunc); // = true

// Should still be false, as normal:
_.isEqualWith({ a: undefined }, { a: 123 }, comparisonFunc); // = false

// Should still be false, as normal:
_.isEqualWith([undefined], [ ], comparisonFunc); // = false

如果有人有更简单或更好的东西,我很乐意接受其他答案:-)


0
投票

您可以检查是否是数组或对象并相应地过滤

undefined
成员,然后递归调用就是这样。

const comp = (a, b) => {
  var A, B,
      fn = v => !_.isUndefined(v),
      filter = _.isArray(a)  ? _.filter : _.pickBy;
	if (_.isObject(a)) {
		A = filter(a, fn)
		B = filter(b, fn)
	} else { return _.isEqual(a, b); } 

	if (_.keys(a).length === _.keys(A).length && _.keys(b).length === _.keys(B).length) {return}
	return _.isEqualWith(A, B, comp);
};

var a1 = [10, 10, undefined, undefined, 10],
    a2 = [undefined, undefined, 10, undefined, 10, undefined, 10],
    o1 = {x: 10, y:undefined, z: 20, v: a1}
    o2 = {x: 10, z: 20, v: a2};

console.log('a1 with a2: ', _.isEqualWith(a1, a2, comp));
console.log('o1 with o2: ', _.isEqualWith(o1, o2, comp));
console.log('a1 with o2: ', _.isEqualWith(a1, o2, comp));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

检查密钥长度和返回语句是为了确定我们是否必须在内部进行遍历(我们在上次迭代中删除了未定义的值),或者我们需要再次遍历它(因为我们在本次迭代中删除了未定义的值)


0
投票

与 Tim Perry 的答案相同,仅使用 TypeScript 和

lodash/fp


function matchMissingWithUndefined(a: {}, b: {}) {
  const hasUndefined = _.includes(undefined);
  if (_.isPlainObject(a) && _.isPlainObject(b) && (hasUndefined(a) || hasUndefined(b))) {
    const onlyDefined = _.omitBy((value) => value === undefined);
    return _.isEqualWith(matchMissingWithUndefined, onlyDefined(a), onlyDefined(b));
  }
}

_.isEqualWith(matchMissingWithUndefined, { a: undefined }, { }); // true


0
投票

省略

null
值后,我们应该以某种方式绕过对
customizer
的初始调用,而不检查该对象是否再次具有
includes
null
值。

我为此目的发明了某种不错的自行车:

const compareWithoutNullProperties = (a: any, b: any) =>
  isPlainObject(a) && isPlainObject(b)
    ? isEqualWith(
      omitBy(a, (value) => value == null),
      omitBy(b, (value) => value == null),
      (a: any, b: any, key?: number | string | symbol): boolean | undefined =>
        // Next initial call should be ignored.
        key != null ? compareWithoutNullProperties(a, b) : undefined,
    )
    : undefined;

const isEqualWithoutNullProperties = (a: any, b: any) =>
  isEqualWith(a, b, compareWithoutNullProperties);

测试返回

true

isEqualWithoutNullProperties({ a: undefined }, {});
isEqualWithoutNullProperties({ a: null }, {});
isEqualWithoutNullProperties([{ a: undefined }], [{}]);
isEqualWithoutNullProperties([{ a: null }], [{}]);
isEqualWithoutNullProperties({ a: { a: undefined } }, { a: {} });
isEqualWithoutNullProperties({ a: { a: null } }, { a: {} });
isEqualWithoutNullProperties({ a: [{ a: undefined }] }, { a: [{}] });
isEqualWithoutNullProperties({ a: [{ a: null }] }, { a: [{}] });

测试返回

false

isEqualWithoutNullProperties([undefined], []);
isEqualWithoutNullProperties([null], []);
isEqualWithoutNullProperties([undefined], [1]);
isEqualWithoutNullProperties([null], [1]);
isEqualWithoutNullProperties({ a: undefined }, { a: 1 });
isEqualWithoutNullProperties({ a: null }, { a: 1 });
isEqualWithoutNullProperties([{ a: undefined }], [{ a: 1 }]);
isEqualWithoutNullProperties([{ a: null }], [{ a: 1 }]);
isEqualWithoutNullProperties({ a: { a: undefined } }, { a: { a: 1 } });
isEqualWithoutNullProperties({ a: { a: null } }, { a: { a: 1 } });
isEqualWithoutNullProperties({ a: [{ a: undefined }] }, { a: [{ a: 1 }] });
isEqualWithoutNullProperties({ a: [{ a: null }] }, { a: [{ a: 1 }] });

0
投票

我们可以在比较之前简单地预处理对象

_.isEqual(_.omitBy({ a: undefined }, _.isNil), _.omitBy({}, _.isNil)); // true
_.isEqual(_.omitBy({ a: undefined }, _.isNil), _.omitBy({ a: 123 }, _.isNil)); // false
© www.soinside.com 2019 - 2024. All rights reserved.