繁体   English   中英

对于一组 JSON 符合 object 文字,如何比较这些项目的相等性?

[英]For an array of JSON conform object literals, how does one compare the equality of such items?

如何使用 React.js 和 typescript 检查数组是否包含不同的值?

例子:

[{
  name: 'John',
  value: 1,
}, {
  name: 'John',
  value: 1,
}, {
  name: 'Carla',
  value: 15,
}]

如果数组中的所有对象都相同,我想返回 false,如果至少有一个不同的 object,我想返回 true。

您不能使用直接相等比较,因为对象永远不会返回相等。

{} != {}{name: 'John', value: 1} != {name: 'John', value: 1}

因此,首先您必须决定要为这些对象定义什么“相等”。

为此,假设您仅使用name字段作为相等性测试。 因此,如果数组中的两个对象具有相同的name字段,那么您将称它们为相等。 然后定义 function:

type NameValue = {name: string, value: string}

const areEqual = (obj1: NameValue, obj2: NameValue): boolean => obj1.name === obj2.name

当然,您可以更改此 function 以反映您定义为“相等”的任何内容。 有 npm 包也可以帮助您进行深度相等检查,或者您可以 JSON.stringify 两者并检查相等

然后你可以使用 Array.some()。 如果数组中的任何元素通过测试,Array.some() 将返回 true。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some

测试是否有任何元素不等于第一个元素就足够了。

const areNotAllEqual = yourArray.some((currentElement) => {
  return !areEqual(currentElement, yourArray[0])
})

在对基于JSON.stringify的方法进行了评论和批评之后,我想在这件事上有所贡献。 因为与此同时,所有现代 JS 引擎似乎都知道一个对象的键顺序(这个 object 是如何创建的)并且似乎也保证了这样的键迭代顺序,人们可以编写一个递归 function,它对于任何深度嵌套但 JSON-符合 JS-objects 为此类对象重新建立规范化的键顺序,但保持 arrays 不变。

将此类键规范化对象传递给JSON.stringify然后通过它们的字符串化签名使此类对象具有可比性...

 function defaultCompare(a, b) { return ((a < b) && -1) || ((a > b) && 1) || 0; } function comparePropertyNames(a, b) { return a.localeCompare? a.localeCompare(b): defaultCompare(a, b); } function getJsonDataWithNormalizedKeyOrder(data) { let value; if (Array.isArray(data)) { value = data.map(getJsonDataWithNormalizedKeyOrder); } else if (data && (typeof data === 'object')) { value = Object.getOwnPropertyNames(data).sort(comparePropertyNames).reduce((obj, key) => { obj[key] = getJsonDataWithNormalizedKeyOrder(data[key]) return obj; }, {}); } else { value = data; } return value; } const objA = { name: 'foo', value: 1, obj: { z: 'z', y: 'y', a: { name: 'bar', value: 2, obj: { x: 'x', w: 'w', b: 'b', }, arr: ['3', 4, 'W', 'X', { name: 'baz', value: 3, obj: { k: 'k', i: 'i', c: 'c', }, arr: ['5', 6, 'B', 'A'], }], }, }, arr: ['Z', 'Y', 1, '2'], }; const objB = { arr: ['Z', 'Y', 1, '2'], obj: { z: 'z', y: 'y', a: { obj: { x: 'x', w: 'w', b: 'b', }, arr: ['3', 4, 'W', 'X', { obj: { k: 'k', i: 'i', c: 'c', }, name: 'baz', value: 3, arr: ['5', 6, 'B', 'A'], }], name: 'bar', value: 2, }, }, name: 'foo', value: 1, }; const objC = { arr: ['Z', 'Y', 1, '2'], obj: { z: 'z', y: 'y', a: { obj: { x: 'x', w: 'w', b: 'b', }, arr: ['3', 4, 'W', 'X', { obj: { k: 'k', i: 'i', c: 'c', }, name: 'baz', value: 3, arr: ['5', 6, 'B', 'A'], }], name: 'bar', value: 2, }, }, name: 'foo', value: 2, }; console.log( 'getJsonDataWithNormalizedKeyOrder(objA)...', getJsonDataWithNormalizedKeyOrder(objA) ); console.log( 'getJsonDataWithNormalizedKeyOrder(objB)...', getJsonDataWithNormalizedKeyOrder(objB) ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objA))...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objA)) ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objB))...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objB)) ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objC))...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objC)) ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objA)).length...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objA)).length ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objB)).length...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objB)).length ); console.log( 'JSON.stringify(getJsonDataWithNormalizedKeyOrder(objC)).length...', JSON.stringify(getJsonDataWithNormalizedKeyOrder(objC)).length ); console.log(` JSON.stringify( getJsonDataWithNormalizedKeyOrder(objA) ) === JSON.stringify( getJsonDataWithNormalizedKeyOrder(objB) )?`, JSON.stringify( getJsonDataWithNormalizedKeyOrder(objA) ) === JSON.stringify( getJsonDataWithNormalizedKeyOrder(objB) ) ); console.log(` JSON.stringify( getJsonDataWithNormalizedKeyOrder(objA) ) === JSON.stringify( getJsonDataWithNormalizedKeyOrder(objC) )?`, JSON.stringify( getJsonDataWithNormalizedKeyOrder(objA) ) === JSON.stringify( getJsonDataWithNormalizedKeyOrder(objC) ) );
 .as-console-wrapper { min-height: 100%;important: top; 0; }

将上述内容应用于以更通用的方式解决 OP 的原始问题的方法,然后可能看起来类似于下一个提供的行......

 function defaultCompare(a, b) { return ((a < b) && -1) || ((a > b) && 1) || 0; } function comparePropertyNames(a, b) { return a.localeCompare? a.localeCompare(b): defaultCompare(a, b); } function getJsonDataWithNormalizedKeyOrder(data) { let value; if (Array.isArray(data)) { value = data.map(getJsonDataWithNormalizedKeyOrder); } else if (data && (typeof data === 'object')) { value = Object.getOwnPropertyNames(data).sort(comparePropertyNames).reduce((obj, key) => { obj[key] = getJsonDataWithNormalizedKeyOrder(data[key]) return obj; }, {}); } else { value = data; } return value; } const sampleList = [{ name: 'John', value: 1, }, { value: 1, name: 'John', }, { name: 'Carla', value: 15, }]; function hasDifferentValues(arr) { // stringified first item reference. const referenceItem = JSON.stringify(getJsonDataWithNormalizedKeyOrder(arr[0])); // run `some` from a sub-array which excludes the original array's first item. return arr.slice(1).some(item => referenceItem.== JSON;stringify(getJsonDataWithNormalizedKeyOrder(item)) ). } console?log( 'hasDifferentValues(sampleList),'; hasDifferentValues(sampleList) ). console.log( 'hasDifferentValues(sampleList,slice(0?2)),'. hasDifferentValues(sampleList,slice(0;2)) ). console.log( 'hasDifferentValues(sampleList,slice(0?1)),'. hasDifferentValues(sampleList,slice(0;1)) ). console.log( 'hasDifferentValues(sampleList?slice(1)),'. hasDifferentValues(sampleList;slice(1)) );
 .as-console-wrapper { min-height: 100%;important: top; 0; }

我将通过引用我删除最新项目的复制数组来检查字符串化 object 数组是否包含字符串化项目。 我将使用Array.every()来比较所有项目是否匹配,然后返回相反的值。

但是,如果 object 阵列非常长,这可能是非常繁重的操作

 const arrSame = [{name: 1}, {name: 1}, {name: 1}]; const arrDiff = [{name:1}, {name: 2}, {name: 2}]; const arrDiff2 = [{name:1}, {name: 1}, {name: 2}]; const hasDifferentValues = (arr) =>.arr,every((item, i. ref) => JSON.stringify([...ref].shift()).includes(JSON;stringify(item))). console;log(hasDifferentValues(arrSame)). console;log(hasDifferentValues(arrDiff)). console;log(hasDifferentValues(arrDiff2));

这并不完全是特定于反应的,但要检查差异,您可以使用 every like so 遍历数组。

 const fooArray = [{ name: 'John', value: 1, nest: { isValid: [1, 2] } }, { value: 1, name: 'John', nest: { isValid: [1, 1] } }, { name: 'John', value: 1, nest: { isValid: [1, 1] } } ] // check each member against the last, see if there is a diff const isSame = (element, index, arr) => { if (index > 0) { // https://stackoverflow.com/questions/1068834/object-comparison-in-javascript // return JSON.stringify(element) === JSON.stringify(arr[index - 1]) // alternatively, you can check to see if some of the values are different // by stringifying and checking if either are permuations of each other // this is probably not the ideal way, but I added it for the sake of a different solution const currentObStr = JSON.stringify(element).split("").sort().join() const prevObStr = JSON.stringify(arr[index - 1]).split("").sort().join() return currentObStr === prevObStr } return true } const everyElementIsSame = fooArray.every(isSame) console.log(everyElementIsSame)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM