js判断两个object为子元素的数组是否相等,并提取差异项?

  • 10

怎么判断这两个数组的object是否相等呢,需要的是不排序也能进行比较。

var list = [
            {
               "dept_name": "妇科门诊1", "q_type": 0, "room": "妇科一诊室",
               "queue_time": "2021-04-18 09:31:03", "doctor": "莫春璘",
              "patient_id": 66656, "patient_name": "张家荣", "id": 36999,
               "dept_id": 99, "status": 7
          },
          {
               "dept_name": "妇科门诊1", "q_type": 0,
                "room": "妇科二诊室", "queue_time": "2021-04-18 09:31:03",
                "doctor": "莫春璘", "patient_id": 66657, "patient_name": "杨淑君",
                "id": 37000, "dept_id": 99, "status": 7
            },
             {
                "dept_name": "妇科门诊1", "q_type": 0,
                "room": "妇科三诊室", "queue_time": "2021-04-18 09:31:03",
                "doctor": "莫春璘", "patient_id": 66658, "patient_name": "吴俊明",
               "id": 37001, "dept_id": 99, "status": 7
            },
]
var list2 = [
            {
               "dept_name": "妇科门诊1", "q_type": 0, 
               "room": "妇科二诊室","queue_time": "2021-04-18 09:31:03", 
                "doctor": "莫春璘","patient_id": 66656, "patient_name": "张家荣", 
                "id": 36999,"dept_id": 99, "status": 7
          },
          {
               "dept_name": "妇科门诊1", "q_type": 0,
                "room": "妇科二诊室", "queue_time": "2021-04-18 09:31:03",
                "doctor": "莫春璘", "patient_id": 66657, "patient_name": "杨淑君",
                "id": 37000, "dept_id": 99, "status": 7
            },

]

向大神求教!!

可能我描述的不是很清楚,想要的结果不是两个数组是否相等,是数组内的object是否有相等的,如果object相等的话,就把不相等的重新构建一个新数组

回复
阅读 1.3k
3 个回答

题目修改后的最新回答:

利用deep比较,加个去重就行

// 先获取list有,list2没有的元素
const diff1 = list.filter(m => !list2.find(w => deepCompare(m,w)))
// 先获取list2有,list没有的元素
const diff2 = list2.filter(m => !list.find(w => deepCompare(m,w)))
// 拼接
const diff = diff1.concat(diff2)
console.log(diff)

以下为题目修改前的回答:

function deepCompare () {
  var i, l, leftChain, rightChain;

  function compare2Objects (x, y) {
    var p;

    // remember that NaN === NaN returns false
    // and isNaN(undefined) returns true
    if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
         return true;
    }

    // Compare primitives and functions.     
    // Check if both arguments link to the same object.
    // Especially useful on the step where we compare prototypes
    if (x === y) {
        return true;
    }

    // Works in case when functions are created in constructor.
    // Comparing dates is a common scenario. Another built-ins?
    // We can even handle functions passed across iframes
    if ((typeof x === 'function' && typeof y === 'function') ||
       (x instanceof Date && y instanceof Date) ||
       (x instanceof RegExp && y instanceof RegExp) ||
       (x instanceof String && y instanceof String) ||
       (x instanceof Number && y instanceof Number)) {
        return x.toString() === y.toString();
    }

    // At last checking prototypes as good as we can
    if (!(x instanceof Object && y instanceof Object)) {
        return false;
    }

    if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
        return false;
    }

    if (x.constructor !== y.constructor) {
        return false;
    }

    if (x.prototype !== y.prototype) {
        return false;
    }

    // Check for infinitive linking loops
    if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
         return false;
    }

    // Quick checking of one object being a subset of another.
    // todo: cache the structure of arguments[0] for performance
    for (p in y) {
        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
            return false;
        }
        else if (typeof y[p] !== typeof x[p]) {
            return false;
        }
    }

    for (p in x) {
        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
            return false;
        }
        else if (typeof y[p] !== typeof x[p]) {
            return false;
        }

        switch (typeof (x[p])) {
            case 'object':
            case 'function':

                leftChain.push(x);
                rightChain.push(y);

                if (!compare2Objects (x[p], y[p])) {
                    return false;
                }

                leftChain.pop();
                rightChain.pop();
                break;

            default:
                if (x[p] !== y[p]) {
                    return false;
                }
                break;
        }
    }

    return true;
  }

  if (arguments.length < 1) {
    return true; //Die silently? Don't know how to handle such case, please help...
    // throw "Need two or more arguments to compare";
  }

  for (i = 1, l = arguments.length; i < l; i++) {

      leftChain = []; //Todo: this can be cached
      rightChain = [];

      if (!compare2Objects(arguments[0], arguments[i])) {
          return false;
      }
  }

  return true;
}

用法:

deepCompare(1,2) //false
deepCompare(1,1) //true
deepCompare(1,1,2) //false
deepCompare(1,1,1) //true
deepCompare({a:1,b:2},{b:2,a:1}) //true
deepCompare({a:1,c:3,b:2},{c:3,b:2,a:1},{b:2,a:1,c:3})//true

另外,有两个很好用的深度比较模块deep-equal , fast-deep-equal;

npm install deep-equal

var deepCompare = require('deep-equal');

deepCompare(1,2) //false
deepCompare(1,1) //true

deepCompare({a:1,b:2},{b:2,a:1}) //true

前端使用deep-equal 例子, 基于umi和ts

import styles from './index.less';
import deepEqual from 'deep-equal';

export default function IndexPage() {
  let equal = deepEqual(1,1);
  console.log(equal)
  return (
    <div>
      <h1 className={styles.title}>Equal: {equal.toString()}</h1>
    </div>
  );
}

简单的做法:先根据某个key比如id进行排序,再用JSON.stringify来比较

function arraysEqual(a1, a2) {
  return (
    JSON.stringify(a1.sort((a, b) => a.id - b.id)) ==
    JSON.stringify(a2.sort((a, b) => a.id - b.id))
  );
}

如果你的对象数组中子对象的结构是相似的(大多数key都相同),则找一个所有key的集合再比较。

此外比较麻烦的是,你要比较的是2个数组,你也没有规定输出要求(全等,或者求交集),不过一些通用的加速处理的方法还是有的

  1. 提取一定有的key,再排序比较,可以很快判断是否有可能全等或者有交集。
  2. 再此基础上,再逐一比较key属性来进一步比较。
你知道吗?

宣传栏