如何通过两个对象打字稿角度6进行比较

Posted

技术标签:

【中文标题】如何通过两个对象打字稿角度6进行比较【英文标题】:How to compare by two objects typescript angular6 【发布时间】:2019-02-02 14:45:55 【问题描述】:

我想比较两个 Json 对象数组。一个有更多的数据。对于最终结果,如果一个 id 找到另一个,则选中的复选框 = true。到目前为止有4个,它只找到一个。我是否先循环遍历长数组,然后循环遍历第二个数组以查找匹配项?

 this.formAll = JSON.parse(response)
      for (var i = 0; i < this.formAll.length; i++) 
        for (var j = i; j <  this.formAb.length; j++) 
         console.log( this.formAb[j].id,  this.formAll[i].SeriesNumber);
          if ( this.formAll[i].id === this.formAb[j].id) 
            console.log( 'small=', this.formAb[j].id, 'large=', 
         this.formAll[i].id );
         this.formAll[i].selected = true;
        
      

【问题讨论】:

请标记有效答案 【参考方案1】:

快速而有限

JSON.stringify(obj1) === JSON.stringify(obj2)

缓慢而通用

Object.equals = function( x, y ) 
    if ( x === y ) return true;
    // if both x and y are null or undefined and exactly the same

    if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) return false;
    // if they are not strictly equal, they both need to be Objects

    if ( x.constructor !== y.constructor ) return false;
    // they must have the exact same prototype chain, the closest we can do is
    // test there constructor.

    for ( var p in x ) 
        if ( ! x.hasOwnProperty( p ) ) continue;
        // other properties were tested using x.constructor === y.constructor

       if ( ! y.hasOwnProperty( p ) ) return false;
       // allows to compare x[ p ] and y[ p ] when set to undefined

       if ( x[ p ] === y[ p ] ) continue;
       // if they have the same strict value or identity then they are equal

       if ( typeof( x[ p ] ) !== "object" ) return false;
       // Numbers, Strings, Functions, Booleans must be strictly equal

       if ( ! Object.equals( x[ p ],  y[ p ] ) ) return false;
       // Objects and Arrays must be tested recursively
   

   for ( p in y ) 
      if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) ) return false;
      // allows x[ p ] to be set to undefined
    
    return true;

【讨论】:

不要向内置运行时实体添加属性。此属性将来可能会成为标准,不一定以相同的方式实现。【参考方案2】:

在 Javascript/Typescript 中(如果两个对象的键顺序相同):使用

    JSON.stringify(obj1) === JSON.stringify(obj2) Object.entries(obj1).toString() === Object.entries(obj2).toString()

obj1 = a:1, b:2 obj2 = a:1, b:2 // true

obj1 = a:1, b:2 obj2 = b:2, a:1 // false

    使用 Lodash ,无论键的顺序如何

    _.isEqual(obj1 , obj2 ); // true

    分别比较对象的每个键

【讨论】:

【参考方案3】:

对于 Angular 使用 Deep Equal

import * as deepEqual from "deep-equal";

console.log(deepEqual(a:123,a:123)); // True

【讨论】:

当心。 deepEqualdeepStrictEqual 替换,返回类型不是 bool,而是一个 asswerts,如下所示:function deepStrictEqual&lt;T&gt;(actual: any, expected: T, message?: string | Error): asserts actual is T; 在此处阅读有关 asserts 的更多信息:typescriptlang.org/docs/handbook/release-notes/…【参考方案4】:

简单易行!!

如果对象键相同且有序,JSON.stringify(Obj2) 工作最快:

Obj1 =  fruit: '?' ;
Obj2 =  fruit: '?' ;

JSON.stringify(Obj1) === JSON.stringify(Obj2);

【讨论】:

这个答案已经给出,请尝试解释更多,否则这个答案将无济于事。 并非总是如此。如果你对两个对象进行字符串化,属性中的顺序可能不一定是相同的,这意味着两个字符串会有很大的不同【参考方案5】:

您可以使用 for-of 和 find 方法获得结果,例如:

for(let item  of this.formAll) 
    if (this.formAb.find((i) =>  i.id === item.id))
       item.selected = true;
    

【讨论】:

【参考方案6】:

使用过滤器效果更好。

   this.formAll = JSON.parse(response)
    this.formAll.forEach((element) => 
      this.formAb.filter((element1) => 
        if (element1.id === element.id ) 
          element.selected = true;
        
     )
     )

【讨论】:

【参考方案7】:

比较两个 Json 对象的例子: 对象 1:


id : 1,
name : 'HADY',
status : false


对象 2:


id : 1,
name : 'example',
surename : 'example',
nickname : 'example'
status : true

----------------------------------------------- -比较(obj1,obj2)

  const keys1 = [];
    const values1 = [];
    Object.keys(obj1).forEach((element) => 
      keys1.push(element);
    );
    Object.values(obj1).forEach((element) => 
      values1.push(element);
    );
    const keys2 = [];
    const values2 = [];
    Object.keys(obj2).forEach((element) => 
      keys2.push(element);
    );
    Object.values(obj2).forEach((element) => 
      values2.push(element);
    );
    const obj = ;
    keys1.forEach((element, i) => 
      for (let index = 0; index < keys2.length; index++) 
        if (element === keys2[index]) 
          if (values1[i] !== values2[index]) 
            const jsonKey = element;
            obj[jsonKey] = values1[i];
          
          break;
        
      
    );
    console.log(obj);
    return obj;
  

它只会返回尊重: 对象


name : 'HADY',
status : false

【讨论】:

【参考方案8】:

我认为比较“JSON.Stringify”方法不正确; 下一个检查递归对象的变体:

interface IComparator<T> 
  equals(obj: T, other: T): boolean;


export default class Comparator<T> implements IComparator<T> 
  equals(item: T, otherItem: T): boolean 
    if (typeof item !== typeof otherItem) 
      return false;
    

    const objectCache: any[] = [];
    const otherObjectCache: any[] = [];
    const getIndexFromCache = (compareObject: any, cacheArray: any[]): number =>
      cacheArray.findIndex((item) => item === compareObject);

    switch (true) 
      case item === otherItem:
        return true;
      case typeof item !== 'object':
        return item === otherItem;
      case item === null || otherItem === null:
        return item === null && otherItem === null;
      case Object.keys(item).length !== Object.keys(otherItem).length:
        return false;
      default:
        const object = item as any;
        const otherObject = otherItem as any;

        return Object.keys(object).every((key: string) => 
          const hasKeyInOtherObject = Object.prototype.hasOwnProperty.call(otherItem, key);

          if (!hasKeyInOtherObject) 
            return false;
          

          const cacheObjectIndex = getIndexFromCache(object[key], objectCache);
          const cacheOtherObjectIndex = getIndexFromCache(otherObject[key], otherObjectCache);

          if (cacheObjectIndex !== cacheOtherObjectIndex) 
            return false;
          

          const isEqualsCacheObjects =
            cacheObjectIndex !== -1 && cacheOtherObjectIndex !== -1 && cacheObjectIndex === cacheOtherObjectIndex;

          if (isEqualsCacheObjects) 
            return true;
          

          objectCache.push(object[key]);
          otherObjectCache.push(otherObject[key]);

          return new Comparator<any>().equals(object[key], otherObject[key]);
        );
    
  

并开玩笑地测试它:

import Comparator from './Comparator';

export default describe('Comparator', () => 
  const recursiveA:  value: number; b?: any  =  value: 1 ;
  const recursiveB:  value: number; a?: any  =  value: 2 ;

  recursiveA.b = recursiveB;
  recursiveB.a = recursiveA;

  it.each([
    [null, null, true],
    [undefined, undefined, true],
    [1, 1, true],
    ['test', 'test', true],
    [[1, 2], [1, 2], true],
    [ a: 1, b: 3 ,  a: 1, b: 3 , true],
    [2, 1, false],
    ['test', 'test2', false],
    [[1, 2], [2, 1], false],
    [ a: 1, b: 3 ,  a: 3, b: 1 , false],
    [recursiveA, recursiveB, false],
    [null, 1, false],
    [null, , false],
    [undefined, null, false],
    [1, '1', false],
  ])('compares values %o and %o are equal: %s', (value1: any, value2: any, expectedResult: boolean) => 
    const comparator = new Comparator<any>();
    const actualResult = comparator.equals(value1, value2);

    expect<boolean>(actualResult).toBe(expectedResult);
  );
);

javascript版本:

export default class Comparator 
    equals(item, otherItem) 
        if (typeof item !== typeof otherItem) 
            return false;
        

        const objectCache = [];
        const otherObjectCache = [];
        const getIndexFromCache = (compareObject, cacheArray) => cacheArray.findIndex((item) => item === compareObject);

        switch (true) 
            case item === otherItem:
                return true;
            case typeof item !== 'object':
                return item === otherItem;
            case item === null || otherItem === null:
                return item === null && otherItem === null;
            case Object.keys(item).length !== Object.keys(otherItem).length:
                return false;
            default:
                const object = item;
                const otherObject = otherItem;

                return Object.keys(object).every((key) => 
                    const hasKeyInOtherObject = Object.prototype.hasOwnProperty.call(otherItem, key);

                    if (!hasKeyInOtherObject) 
                        return false;
                    

                    const cacheObjectIndex = getIndexFromCache(object[key], objectCache);
                    const cacheOtherObjectIndex = getIndexFromCache(otherObject[key], otherObjectCache);

                    if (cacheObjectIndex !== cacheOtherObjectIndex) 
                        return false;
                    

                    const isEqualsCacheObjects = cacheObjectIndex !== -1 && cacheOtherObjectIndex !== -1 && cacheObjectIndex === cacheOtherObjectIndex;

                    if (isEqualsCacheObjects) 
                        return true;
                    

                    objectCache.push(object[key]);
                    otherObjectCache.push(otherObject[key]);

                    return new Comparator().equals(object[key], otherObject[key]);
                );
        
    

【讨论】:

以上是关于如何通过两个对象打字稿角度6进行比较的主要内容,如果未能解决你的问题,请参考以下文章

在角度/打字稿中将类创建为可迭代

如何让 Jest 自定义匹配器在打字稿中工作?

如何在具有角度注入参数的打字稿中创建新对象

在打字稿中使用角度为 6 的节点短 id 模块

使用角度,打字稿,webpack时如何将jquery添加到窗口对象

如何将从webapi返回的自定义对象数组的HttpResponse响应分配给打字稿角度中相同数组类型的对象?