代码之家  ›  专栏  ›  技术社区  ›  AdamB

比较javascript中的对象数组

  •  42
  • AdamB  · 技术社区  · 16 年前

    我想比较两个javascript代码中的对象数组。对象总共有8个属性,但每个对象都不会有一个值,数组也永远不会超过每个8个项,所以可能最简单的方法是遍历每个对象,然后查看8个属性的值,但在实现之前,我想看看是否有人有一个更优雅的解决方案。有什么想法吗?

    9 回复  |  直到 6 年前
        1
  •  38
  •   Community CDub    8 年前

    编辑:在当前基于浏览器的JavaScript解释器实现中,不能重载运算符。

    为了回答最初的问题,你可以这样做,记住,这是一个有点黑客,简单地说 serialize the two arrays to JSON 然后比较两个JSON字符串。这只会告诉你数组是否不同,显然你可以这样做 每个 在数组中查看哪些对象是不同的。

    另一种选择是使用一个库,它有一些很好的工具来比较对象-我使用并推荐 MochiKit .


    编辑: The answer kamens gave 同样值得考虑,因为比较两个给定对象的单个函数比任何库都要小得多,可以按照我的建议进行操作(尽管我的建议肯定足够有效)。

    这是一个很幼稚的暗示,可能对你来说已经足够了-请注意,这种实施存在潜在的问题:

    function objectsAreSame(x, y) {
       var objectsAreSame = true;
       for(var propertyName in x) {
          if(x[propertyName] !== y[propertyName]) {
             objectsAreSame = false;
             break;
          }
       }
       return objectsAreSame;
    }
    

    假设两个对象具有相同的属性列表。

    哦,很明显,不管好坏,我只属于一个返回点营地。:)

        2
  •  15
  •   Mr.Wizard naktepe    14 年前

    我知道这是个老问题,答案很好…但这要短一点,不需要任何额外的库(即JSON):

    function arraysAreEqual(ary1,ary2){
      return (ary1.join('') == ary2.join(''));
    }
    
        3
  •  13
  •   kamens    16 年前

    老实说,每个对象最多8个对象,最多8个属性,您最好只遍历每个对象并直接进行比较。它会很快很容易。

    如果您经常使用这些类型的比较,那么我同意Jason关于JSON序列化的观点……否则就不需要使用新的库或JSON序列化代码来减慢应用程序的速度。

        4
  •  9
  •   Alexander Elgin    7 年前

    我做了一些简单的算法来比较两个对象的内容并返回一个可理解的差异列表。以为我会分享。它为jquery借用了一些想法,即 map 函数实现和对象和数组类型检查。

    它返回“diff对象”列表,这些对象是具有diff信息的数组。这很简单。

    这里是:

    // compare contents of two objects and return a list of differences
    // returns an array where each element is also an array in the form:
    // [accessor, diffType, leftValue, rightValue ]
    //
    // diffType is one of the following:
    //   value: when primitive values at that index are different
    //   undefined: when values in that index exist in one object but don't in 
    //              another; one of the values is always undefined
    //   null: when a value in that index is null or undefined; values are
    //         expressed as boolean values, indicated wheter they were nulls
    //   type: when values in that index are of different types; values are 
    //         expressed as types
    //   length: when arrays in that index are of different length; values are
    //           the lengths of the arrays
    //
    
    function DiffObjects(o1, o2) {
        // choose a map() impl.
        // you may use $.map from jQuery if you wish
        var map = Array.prototype.map?
            function(a) { return Array.prototype.map.apply(a, Array.prototype.slice.call(arguments, 1)); } :
            function(a, f) { 
                var ret = new Array(a.length), value;
                for ( var i = 0, length = a.length; i < length; i++ ) 
                    ret[i] = f(a[i], i);
                return ret.concat();
            };
    
        // shorthand for push impl.
        var push = Array.prototype.push;
    
        // check for null/undefined values
        if ((o1 == null) || (o2 == null)) {
            if (o1 != o2)
                return [["", "null", o1!=null, o2!=null]];
    
            return undefined; // both null
        }
        // compare types
        if ((o1.constructor != o2.constructor) ||
            (typeof o1 != typeof o2)) {
            return [["", "type", Object.prototype.toString.call(o1), Object.prototype.toString.call(o2) ]]; // different type
    
        }
    
        // compare arrays
        if (Object.prototype.toString.call(o1) == "[object Array]") {
            if (o1.length != o2.length) { 
                return [["", "length", o1.length, o2.length]]; // different length
            }
            var diff =[];
            for (var i=0; i<o1.length; i++) {
                // per element nested diff
                var innerDiff = DiffObjects(o1[i], o2[i]);
                if (innerDiff) { // o1[i] != o2[i]
                    // merge diff array into parent's while including parent object name ([i])
                    push.apply(diff, map(innerDiff, function(o, j) { o[0]="[" + i + "]" + o[0]; return o; }));
                }
            }
            // if any differences were found, return them
            if (diff.length)
                return diff;
            // return nothing if arrays equal
            return undefined;
        }
    
        // compare object trees
        if (Object.prototype.toString.call(o1) == "[object Object]") {
            var diff =[];
            // check all props in o1
            for (var prop in o1) {
                // the double check in o1 is because in V8 objects remember keys set to undefined 
                if ((typeof o2[prop] == "undefined") && (typeof o1[prop] != "undefined")) {
                    // prop exists in o1 but not in o2
                    diff.push(["[" + prop + "]", "undefined", o1[prop], undefined]); // prop exists in o1 but not in o2
    
                }
                else {
                    // per element nested diff
                    var innerDiff = DiffObjects(o1[prop], o2[prop]);
                    if (innerDiff) { // o1[prop] != o2[prop]
                        // merge diff array into parent's while including parent object name ([prop])
                        push.apply(diff, map(innerDiff, function(o, j) { o[0]="[" + prop + "]" + o[0]; return o; }));
                    }
    
                }
            }
            for (var prop in o2) {
                // the double check in o2 is because in V8 objects remember keys set to undefined 
                if ((typeof o1[prop] == "undefined") && (typeof o2[prop] != "undefined")) {
                    // prop exists in o2 but not in o1
                    diff.push(["[" + prop + "]", "undefined", undefined, o2[prop]]); // prop exists in o2 but not in o1
    
                }
            }
            // if any differences were found, return them
            if (diff.length)
                return diff;
            // return nothing if objects equal
            return undefined;
        }
        // if same type and not null or objects or arrays
        // perform primitive value comparison
        if (o1 != o2)
            return [["", "value", o1, o2]];
    
        // return nothing if values are equal
        return undefined;
    }
    
        5
  •  5
  •   Paul Roub jim    6 年前

    我试过 JSON.stringify() 为我工作。

    let array1 = [1,2,{value:'alpha'}] , array2 = [{value:'alpha'},'music',3,4];
    
    JSON.stringify(array1) // "[1,2,{"value":"alpha"}]"
    
    JSON.stringify(array2) // "[{"value":"alpha"},"music",3,4]"
    
    JSON.stringify(array1) === JSON.stringify(array2); // false
    
        6
  •  1
  •   c0deNinja    8 年前

    请试试这个:

    function used_to_compare_two_arrays(a, b)
    {
      // This block will make the array of indexed that array b contains a elements
      var c = a.filter(function(value, index, obj) {
        return b.indexOf(value) > -1;
      });
    
      // This is used for making comparison that both have same length if no condition go wrong 
      if (c.length !== a.length) {
        return 0;
      } else{
        return 1;
      }
    }
    
        7
  •  1
  •   Maxime Pacary    8 年前

    这是我的尝试,使用 Node's assert module +NPM包 object-hash .

    我假设您想检查两个数组是否包含相同的对象,即使这些对象在两个数组之间的顺序不同。

    var assert = require('assert');
    var hash = require('object-hash');
    
    var obj1 = {a: 1, b: 2, c: 333},
        obj2 = {b: 2, a: 1, c: 444},
        obj3 = {b: "AAA", c: 555},
        obj4 = {c: 555, b: "AAA"};
    
    var array1 = [obj1, obj2, obj3, obj4];
    var array2 = [obj3, obj2, obj4, obj1]; // [obj3, obj3, obj2, obj1] should work as well
    
    // calling assert.deepEquals(array1, array2) at this point FAILS (throws an AssertionError)
    // even if array1 and array2 contain the same objects in different order,
    // because array1[0].c !== array2[0].c
    
    // sort objects in arrays by their hashes, so that if the arrays are identical,
    // their objects can be compared in the same order, one by one
    var array1 = sortArrayOnHash(array1);
    var array2 = sortArrayOnHash(array2);
    
    // then, this should output "PASS"
    try {
        assert.deepEqual(array1, array2);
        console.log("PASS");
    } catch (e) {
        console.log("FAIL");
        console.log(e);
    }
    
    // You could define as well something like Array.prototype.sortOnHash()...
    function sortArrayOnHash(array) {
        return array.sort(function(a, b) {
            return hash(a) > hash(b);
        });
    }
    
        8
  •  1
  •   Alexander Elgin    7 年前

    这个 objectsAreSame @jasonbunting's answer中提到的函数对我来说很好。但是,有一个小问题:如果 x[propertyName] y[propertyName] 是对象(对象) typeof x[propertyName] == 'object' ,您需要递归地调用函数,以便进行比较。

        9
  •  1
  •   Henry Sellars    6 年前

    使用洛达什的一些: https://lodash.com/docs/4.17.11#some

    const array1 standardray2 notequal=.some(array1,(a1,idx)=>a1.key1!==array2[idx].key1 a1.key2!==array2[idx].key2 a1.key3!==array2[idx].key3);