У меня был такой же симптом. Основная причина заключалась в том, что «Target Membership» для моего исходного файла не было установлено в правильную цель. Я предполагаю, что мой класс не будет создан и включен в мое приложение.
Чтобы исправить его:
Надеюсь, это поможет кому-то там.
Этот метод отстой, но я оставил его здесь для справки, поэтому другие избегают этого пути:
Использование опции 1 из @ninjagecko лучше всего подходит для меня:
Array.prototype.equals = function(array) {
return array instanceof Array && JSON.stringify(this) === JSON.stringify(array) ;
}
a = [1, [2, 3]]
a.equals([[1, 2], 3]) // false
a.equals([1, [2, 3]]) // true
Он также обрабатывает нулевой и неопределенный случай, так как мы добавляем это в прототип массива и проверяем, что другой аргумент также является массивом.
Если вы используете lodash и не хотите изменять любой массив, вы можете использовать функцию _.xor () . Он сравнивает два массива как множества и возвращает набор, содержащий их разницу. Если длина этой разности равна нулю, два массива по существу равны:
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
_.xor(a, b).length === 0
true
_.xor(b, c).length === 0
true
Используя map()
и reduce()
:
function arraysEqual (a1, a2) {
return a1 === a2 || (
a1 !== null && a2 !== null &&
a1.length === a2.length &&
a1
.map(function (val, idx) { return val === a2[idx]; })
.reduce(function (prev, cur) { return prev && cur; }, true)
);
}
Даже если это показалось бы супер простым, иногда это действительно полезно. Если все, что вам нужно, это увидеть, имеют ли два массива одинаковые элементы, и они находятся в одном порядке, попробуйте следующее:
[1, 2, 3].toString() == [1, 2, 3].toString()
true
[1, 2, 3,].toString() == [1, 2, 3].toString()
true
[1,2,3].toString() == [1, 2, 3].toString()
true
Однако это не работает для расширенных случаев режима, таких как:
[[1,2],[3]].toString() == [[1],[2,3]].toString()
true
Это зависит от того, что вам нужно.
Он обрабатывает все возможные вещи и даже ссылается на себя в структуре объекта. Вы можете увидеть пример в конце кода.
var deepCompare = (function() {
function internalDeepCompare (obj1, obj2, objects) {
var i, objPair;
if (obj1 === obj2) {
return true;
}
i = objects.length;
while (i--) {
objPair = objects[i];
if ( (objPair.obj1 === obj1 && objPair.obj2 === obj2) ||
(objPair.obj1 === obj2 && objPair.obj2 === obj1) ) {
return true;
}
}
objects.push({obj1: obj1, obj2: obj2});
if (obj1 instanceof Array) {
if (!(obj2 instanceof Array)) {
return false;
}
i = obj1.length;
if (i !== obj2.length) {
return false;
}
while (i--) {
if (!internalDeepCompare(obj1[i], obj2[i], objects)) {
return false;
}
}
}
else {
switch (typeof obj1) {
case "object":
// deal with null
if (!(obj2 && obj1.constructor === obj2.constructor)) {
return false;
}
if (obj1 instanceof RegExp) {
if (!(obj2 instanceof RegExp && obj1.source === obj2.source)) {
return false;
}
}
else if (obj1 instanceof Date) {
if (!(obj2 instanceof Date && obj1.getTime() === obj2.getTime())) {
return false;
}
}
else {
for (i in obj1) {
if (obj1.hasOwnProperty(i)) {
if (!(obj2.hasOwnProperty(i) && internalDeepCompare(obj1[i], obj2[i], objects))) {
return false;
}
}
}
}
break;
case "function":
if (!(typeof obj2 === "function" && obj1+"" === obj2+"")) {
return false;
}
break;
default: //deal with NaN
if (obj1 !== obj2 && obj1 === obj1 && obj2 === obj2) {
return false;
}
}
}
return true;
}
return function (obj1, obj2) {
return internalDeepCompare(obj1, obj2, []);
};
}());
/*
var a = [a, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null],
b = [b, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null];
deepCompare(a, b);
*/
null==null
в Javascript (даже больше, null===null
), было бы более уместным рассматривать два нуля как равные в проверке эквивалентности массива тоже?
– Halil Özgür
6 February 2012 в 13:49
arrays_equal([1, [2, 3]],[[1, 2], 3])
вернет true
.
– Dennis
17 February 2012 в 21:42
arrays_equal(["1,2"], ["1,2"])
рассматриваются как равные, а также arrays_equal([], [""])
.
– Mike Samuel
17 February 2012 в 21:44
Это то, что вы должны делать. Не используйте stringify
и < >
.
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
sort
в массиве будет изменять этот массив ... вы можете сначала клонировать ваш массив.
– Dancrumb
28 May 2014 в 16:52
var a= [1, 2, 3, '3'];
var b = [1, 2, 3];
var c = a.filter(function (i) { return ! ~b.indexOf(i); });
alert(c.length);
jQuery не имеет метода сравнения массивов. Однако библиотека Underscore (или сопоставимая библиотека Lodash) имеет такой метод: isEqual и может обрабатывать множество других случаев (например, литералы объектов). Чтобы придерживаться приведенного примера:
var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);
alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));
Кстати: в подстроке есть много других методов, которые jQuery также отсутствует, поэтому это отличное дополнение к jQuery.
EDIT : Как было отмечено в комментариях, вышесказанное теперь работает только в том случае, если оба массива имеют свои элементы в одном порядке, то есть ::
_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false
К счастью, у Javascript есть встроенный метод для решения этой проблемы точная проблема, sort
:
_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true
false|false
. _.isEqual(a,b)
сравнивает элементы массива в соответствии с их порядком, поэтому, если требуется нечувствительное к порядку сравнение, массивы должны быть отсортированы перед сравнением.
– Paul
25 February 2016 в 15:55
Нет простого способа сделать это. Мне тоже это нужно, но мне нужна функция, которая может принимать любые две переменные и проверять равенство. Это включает в себя значения, отличные от объекта, объекты, массивы и любой уровень вложенности.
В вашем вопросе вы указываете на то, что хотите игнорировать порядок значений в массиве. Мое решение по сути не делает этого, но вы можете добиться этого, отсортировав массивы перед сравнением для равенства
. Мне также нужен вариант отливки не-объектов в строки, чтобы [1,2] == = ["1", 2]
Поскольку мой проект использует UnderscoreJs, я решил сделать его mixin, а не автономной функцией.
Вы можете проверить это на http://jsfiddle.net/nemesarial/T44W4/
Вот мой mxin:
_.mixin({
/**
Tests for the equality of two variables
valA: first variable
valB: second variable
stringifyStatics: cast non-objects to string so that "1"===1
**/
equal:function(valA,valB,stringifyStatics){
stringifyStatics=!!stringifyStatics;
//check for same type
if(typeof(valA)!==typeof(valB)){
if((_.isObject(valA) || _.isObject(valB))){
return false;
}
}
//test non-objects for equality
if(!_.isObject(valA)){
if(stringifyStatics){
var valAs=''+valA;
var valBs=''+valB;
ret=(''+valA)===(''+valB);
}else{
ret=valA===valB;
}
return ret;
}
//test for length
if(_.size(valA)!=_.size(valB)){
return false;
}
//test for arrays first
var isArr=_.isArray(valA);
//test whether both are array or both object
if(isArr!==_.isArray(valB)){
return false;
}
var ret=true;
if(isArr){
//do test for arrays
_.each(valA,function(val,idx,lst){
if(!ret){return;}
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}else{
//do test for objects
_.each(valA,function(val,idx,lst){
if(!ret){return;}
//test for object member exists
if(!_.has(valB,idx)){
ret=false;
return;
}
// test for member equality
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}
return ret;
}
});
Вот как вы его используете:
_.equal([1,2,3],[1,2,"3"],true)
Чтобы продемонстрировать вложенность, вы можете сделать это:
_.equal(
['a',{b:'b',c:[{'someId':1},2]},[1,2,3]],
['a',{b:'b',c:[{'someId':"1"},2]},["1",'2',3]]
,true);
С версией JavaScript 1.6 это так же просто:
Array.prototype.equals = function( array ) {
return this.length == array.length &&
this.every( function(this_i,i) { return this_i == array[i] } )
}
Например, [].equals([])
дает true
, а [1,2,3].equals( [1,3,2] )
дает false
.
undefined
был равен null
, 0 и т. Д. - или нет.
– rplantiko
22 February 2016 в 21:40
Проверяйте каждое значение по циклу for после проверки размера массива.
function equalArray(a, b) {
if (a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
} else {
return false;
}
}
Array.prototype.sort()
является неглубоким, а Array.prototype.toString()
преобразует объекты в [object Object]
и выравнивает любые встроенные массивы, что может привести к ложному срабатыванию.
– Nate
28 January 2013 в 04:59
jQuery имеет такой метод для глубокого рекурсивного сравнения .
Внутренняя проверка строгого равенства общего назначения может выглядеть следующим образом:
function deepEquals(obj1, obj2, parents1, parents2) {
"use strict";
var i;
// compare null and undefined
if (obj1 === undefined || obj2 === undefined ||
obj1 === null || obj2 === null) {
return obj1 === obj2;
}
// compare primitives
if (typeof (obj1) !== 'object' || typeof (obj2) !== 'object') {
return obj1.valueOf() === obj2.valueOf();
}
// if objects are of different types or lengths they can't be equal
if (obj1.constructor !== obj2.constructor || (obj1.length !== undefined && obj1.length !== obj2.length)) {
return false;
}
// iterate the objects
for (i in obj1) {
// build the parents list for object on the left (obj1)
if (parents1 === undefined) parents1 = [];
if (obj1.constructor === Object) parents1.push(obj1);
// build the parents list for object on the right (obj2)
if (parents2 === undefined) parents2 = [];
if (obj2.constructor === Object) parents2.push(obj2);
// walk through object properties
if (obj1.propertyIsEnumerable(i)) {
if (obj2.propertyIsEnumerable(i)) {
// if object at i was met while going down here
// it's a self reference
if ((obj1[i].constructor === Object && parents1.indexOf(obj1[i]) >= 0) || (obj2[i].constructor === Object && parents2.indexOf(obj2[i]) >= 0)) {
if (obj1[i] !== obj2[i]) {
return false;
}
continue;
}
// it's not a self reference so we are here
if (!deepEquals(obj1[i], obj2[i], parents1, parents2)) {
return false;
}
} else {
// obj2[i] does not exist
return false;
}
}
}
return true;
};
Тесты:
// message is displayed on failure
// clean console === all tests passed
function assertTrue(cond, msg) {
if (!cond) {
console.log(msg);
}
}
var a = 'sdf',
b = 'sdf';
assertTrue(deepEquals(b, a), 'Strings are equal.');
b = 'dfs';
assertTrue(!deepEquals(b, a), 'Strings are not equal.');
a = 9;
b = 9;
assertTrue(deepEquals(b, a), 'Numbers are equal.');
b = 3;
assertTrue(!deepEquals(b, a), 'Numbers are not equal.');
a = false;
b = false;
assertTrue(deepEquals(b, a), 'Booleans are equal.');
b = true;
assertTrue(!deepEquals(b, a), 'Booleans are not equal.');
a = null;
assertTrue(!deepEquals(b, a), 'Boolean is not equal to null.');
a = function () {
return true;
};
assertTrue(deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
]), 'Arrays are equal.');
assertTrue(!deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': '1'
},
true]
]), 'Arrays are not equal.');
a = {
prop: 'val'
};
a.self = a;
b = {
prop: 'val'
};
b.self = a;
assertTrue(deepEquals(b, a), 'Immediate self referencing objects are equal.');
a.prop = 'shmal';
assertTrue(!deepEquals(b, a), 'Immediate self referencing objects are not equal.');
a = {
prop: 'val',
inside: {}
};
a.inside.self = a;
b = {
prop: 'val',
inside: {}
};
b.inside.self = a;
assertTrue(deepEquals(b, a), 'Deep self referencing objects are equal.');
b.inside.self = b;
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equeal. Not the same instance.');
b.inside.self = {foo: 'bar'};
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equal. Completely different object.');
a = {};
b = {};
a.self = a;
b.self = {};
assertTrue(!deepEquals(b, a), 'Empty object and self reference of an empty object.');
var a = {}, b = {}; a.self = a; b.self = {};
и в некоторых других случаях.
– uKolka
21 May 2013 в 15:23
Если вы хотите проверить, что массивы объектов для равенства и порядка не имеют значения, то есть
areEqual([{id: "0"}, {id: "1"}], [{id: "1"}, {id: "0"}]) // true
, вы должны сначала отсортировать массивы. lodash имеет все необходимые инструменты, объединив sortBy
и isEqual
:
// arr1 & arr2: Arrays of objects
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be 'id'
function areEqual (arr1, arr2, sortProperty) {
return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}
EDIT: Поскольку sortBy
возвращает новый массив, есть не нужно клонировать ваши массивы перед сортировкой. Исходные массивы не будут мутированы.
Обратите внимание, что для lodash's isEqual
порядок имеет значение. Вышеприведенный пример вернет false
, если sortBy
не применяется к каждому массиву в первую очередь.
TypeError: Converting circular structure to JSON
– Aram Kocharyan 8 May 2013 в 14:20