簡體   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