数据处理的一个问题

两个对象 对比 返回属性值不相同的属性

var obj = {
name:'ss',
age:12,
arr:[1,2]
}

var obj1={
name:'aa',
age:'12',
arr:[0,1]
}

obj 和 obj1对比 name属性值不相同
age 的值为 12 和 ’12‘ 用 == 判断 也是相同的 不用处理
数组 的话 [1,2] 相同 ['1','2'] | [1,2]和[0,1]不相同 所以返回 [name,arr]这两个属性
大佬 来啊

阅读 1.8k
2 个回答
/**
 * @param {unknown} m
 * @param {unknown} n
 * @return {Array<number | string | symbol>}
 */
const diff = (function () {
  const IDENTITY_TYPES = [
    ["number", "string"],
  ];

  /**
   * @param {unknown} m
   * @param {unknown} n
   * @return {boolean}
   */
  function isDiff (m, n) {
    return !isIdentityType(m, n) ||
      (
        isPrimitive(m)
          ? m != n
          : isDiffObject(m, n)
      );
  }

  /**
   * @param {unknown} m
   * @param {unknown} n
   * @return {boolean}
   */
  function isDiffObject (m, n) {
    const mKeys = Reflect.ownKeys(m);
    const nKeys = Reflect.ownKeys(n);

    return mKeys.length !== nKeys.length ||
      Array
        .from(new Set([...mKeys, ...nKeys]))
        .some(key => isDiff(m[key], n[key]));
  }

  /**
   * @param {unknown} m
   * @param {unknown} n
   * @return {boolean}
   */
  function isIdentityType (m, n) {
    const mType = typeof m, nType = typeof n;
    return mType === nType ||
      IDENTITY_TYPES.some(
        types => types.includes(mType) && types.includes(nType),
      );
  }

  /**
   * @param {unknown} t
   * @return {boolean}
   */
  function isPrimitive (t) {
    return "object" !== typeof t;
  }

  return function diff (m, n) {
    if (isPrimitive(m) || isPrimitive(n)) {
      throw new TypeError("diff called on non-object");
    }

    const diffKeys = [];

    const keys = new Set([...Reflect.ownKeys(m), ...Reflect.ownKeys(n)]);
    for (const key of keys) {
      if (isDiff(m[key], n[key])) {
        diffKeys.push(key);
      }
    }

    return diffKeys;
  };
})();

这个问题首先需要确定是否对象中只有这3个属性,还是可能有更多的属性?
其次是属性的值范围是否如例子所示,比如name最终是string,age是可以数字化的,arr是数组,且其中的元素是可以数字化的?
如果能确认,则相应处理比较简单,否则就很麻烦。当然,即使这样,在比较arr属性时还需要细化规则,比如 [1,2] 相同 ['1','2'],是否 [1,2] 相同 ['2','1'],即子元素位置关系是否影响结果?

根据下面的讨论,其实关键是2个

  1. 对象属性列表获取(已知2个对象有同样的属性)
  2. 对象属性值的比较

因为值主要涉及 3种情况,数组、数字和字符串,所以如果有一个比较函数能直接比较三者则可以很快得出。

var CompObj=function(Obj1,Obj2){
   let rtArr=[];

   for(var i in Obj1) {
     let tmp1=Obj1[i];
     let tmp2=Obj2[i];
     //下面的代码把所有情况转换为string
     if(tmp1 instanceof Array){
        tmp1=tmp1.sort();
        tmp2=tmp2.sort();
        tmp1=tmp1.join(',');
        tmp2=tmp2.join(',');
     }else{
        tmp1=' '+tmp1;
        tmp2=' '+tmp2;
     }
     if(tmp1!==tmp2){
        rtArr.push(i);
     }
   }
   return rtArr
}
推荐问题
宣传栏