Состояние выигрыша Tic Tac Toe в JavaScript [дубликат]

У меня был такой же симптом. Основная причина заключалась в том, что «Target Membership» для моего исходного файла не было установлено в правильную цель. Я предполагаю, что мой класс не будет создан и включен в мое приложение.

Чтобы исправить его:

  1. Выделите ваш .m-файл.
  2. На правой панели выберите «Инспектор файлов».
  3. В разделе «Целевое членство» убедитесь, что установлен целевой объект сборки.

Надеюсь, это поможет кому-то там.

182
задан Martin Thoma 24 May 2015 в 13:30
поделиться

16 ответов

Этот метод отстой, но я оставил его здесь для справки, поэтому другие избегают этого пути:


Использование опции 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

Он также обрабатывает нулевой и неопределенный случай, так как мы добавляем это в прототип массива и проверяем, что другой аргумент также является массивом.

-1
ответ дан Aram Kocharyan 19 August 2018 в 16:53
поделиться
  • 1
    Вопрос: что произойдет, если массив содержит объект, который имеет свойство, относящееся к одному и тому же объекту? – jusio 7 May 2013 в 20:38
  • 2
    TypeError: Converting circular structure to JSON – Aram Kocharyan 8 May 2013 в 14:20
  • 3
    Спасибо @jusio за указание на это, я сделал это явным в ответе. – Aram Kocharyan 8 May 2013 в 14:22

Если вы используете 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
1
ответ дан Chase Sandmann 19 August 2018 в 16:53
поделиться

Используя 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)
    );
}
2
ответ дан Chitharanjan Das 19 August 2018 в 16:53
поделиться
  • 1
    Это неверный ответ на заданный вопрос. Я пробовал это в jsbin, и он не работает с введенным в вопрос вопросом. – Jaimin 2 August 2016 в 19:52
  • 2
    Поскольку вопрос не на 100% ясен о порядке, этот алгоритм вроде бы ОК. Но он работает плохо, так как он полностью выполняет итерацию над массивом. Для больших массивов это может быть проблемой. – try-catch-finally 15 July 2017 в 08:04

Даже если это показалось бы супер простым, иногда это действительно полезно. Если все, что вам нужно, это увидеть, имеют ли два массива одинаковые элементы, и они находятся в одном порядке, попробуйте следующее:

[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

Это зависит от того, что вам нужно.

5
ответ дан Clawsy 19 August 2018 в 16:53
поделиться

Он обрабатывает все возможные вещи и даже ссылается на себя в структуре объекта. Вы можете увидеть пример в конце кода.

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);
*/
6
ответ дан Community 19 August 2018 в 16:53
поделиться
  • 1
    Поскольку null==null в Javascript (даже больше, null===null), было бы более уместным рассматривать два нуля как равные в проверке эквивалентности массива тоже? – Halil Özgür 6 February 2012 в 13:49
  • 2
    Как указано в , этот ответ , arrays_equal([1, [2, 3]],[[1, 2], 3]) вернет true. – Dennis 17 February 2012 в 21:42
  • 3
    Кроме того, 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;
}
191
ответ дан enyo 19 August 2018 в 16:53
поделиться
  • 1
    (Это не изначально мой код, но человек, пишущий его, не хотел его публиковать) – enyo 8 May 2013 в 10:22
  • 2
    – Umur Kontacı 1 July 2013 в 13:15
  • 3
    Почему код должен быть отсортирован? – Varun Madiath 17 September 2013 в 20:17
  • 4
    @VarunMadiath последний цикл проходит через каждый элемент и сравнивает их. Если массивы не отсортированы, это не сработает, если порядок элементов не совсем одинаковый. – enyo 23 September 2013 в 16:17
  • 5
    Обратите внимание, что вызов sort в массиве будет изменять этот массив ... вы можете сначала клонировать ваш массив. – Dancrumb 28 May 2014 в 16:52
  • 6
    @GijsjanB он работает, если массив содержит одни и те же объекты. Конечно, это не работает, если объекты не идентичны, и вы хотите сравнить сами объекты. Но это был не вопрос. – enyo 4 July 2014 в 22:51
var a= [1, 2, 3, '3'];
var b = [1, 2, 3];

var c = a.filter(function (i) { return ! ~b.indexOf(i); });

alert(c.length);
-1
ответ дан KOstyantin 19 August 2018 в 16:53
поделиться

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
62
ответ дан machineghost 19 August 2018 в 16:53
поделиться
  • 1
    Underscorejs - моя ежедневная используемая библиотека. Его простота должна быть оценена значительно выше. – Jan Stanicek 21 April 2015 в 09:46
  • 2
    Подчерк был заменен более совершенной библиотекой lodash . Поскольку это надмножество подчеркивания, оно также поддерживает _.isEqual (a, b). проверьте этот для более подробной информации. – Kunal Kapadia 30 September 2015 в 13:01
  • 3
    Мне нравится lodash, и он содержит супер-набор функций Underscore ... но это not & quot; superior & quot; и он не "заменен" Нижнее подчеркивание. Во-первых, Lodash был настолько метапрограммирован и микро-оптимизирован, что его исходный код в основном не читается. Это имеет значение, когда (скажем) вы случайно передаете неправильные аргументы функции Lodash / Underscore и должны отлаживать то, что происходит. В этом случае Underscore значительно превосходит , потому что (в отличие от Lodash) вы действительно можете прочитать источник. В конечном счете, ни одна библиотека не превосходит другую, у них просто разные сильные и слабые стороны. – machineghost 30 September 2015 в 16:15
  • 4
    В качестве одной из сторон авторы этих двух библиотек (Джон Дэвид Далтон и Джереми Ашкенас) недавно обсудили перспективы их слияния из-за их общности. Но (как вы увидите, если вы читаете поток GitHub: github.com/jashkenas/underscore/issues/2182 ), это не было очевидным решением. Фактически, AFAIK не было принято решение в течение 3 + месяцев с тех пор, именно потому, что Underscore имеет такие преимущества, как читаемый исходный код, который пользователи Underscore не хотят проигрывать. – machineghost 30 September 2015 в 16:22
  • 5
    Вернемся к теме, это предупреждает 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);
1
ответ дан Nemesarial 19 August 2018 в 16:53
поделиться
100
ответ дан ninjagecko 19 August 2018 в 16:53
поделиться

С версией 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.

18
ответ дан rplantiko 19 August 2018 в 16:53
поделиться
  • 1
    Обычно рекомендуется не изменять / расширять существующие глобальные объекты. – Kunal Kapadia 30 September 2015 в 12:48
  • 2
    лучше использовать ===, а не == правильно? – ChetPrickles 19 February 2016 в 16:41
  • 3
    @ChetPrickles Зависит от того, что вы хотите, как всегда :-) Вы хотите, чтобы 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;
    }
}
21
ответ дан try-catch-finally 19 August 2018 в 16:53
поделиться
  • 1
    Будьте осторожны, если ваш массив содержит ничего, кроме простых значений. Array.prototype.sort() является неглубоким, а Array.prototype.toString() преобразует объекты в [object Object] и выравнивает любые встроенные массивы, что может привести к ложному срабатыванию. – Nate 28 January 2013 в 04:59
  • 2
    Я не понимаю, почему это сокращается: это единственное решение, которое на самом деле вернет пример (недоопределенный) ... – Stefan Haustein 8 May 2013 в 05:16
  • 3
    Было бы неплохо увидеть объяснение, почему это проголосовало. Правда, это может работать неправильно для сложных объектов, но это простое решение, которое решает проблему, представленную в вопросе! и, вероятно, может быть расширен до сложных объектов с использованием правильных строковых представлений объектов – soheildb 10 May 2013 в 23:30
  • 4
  • 5
    Его можно считать оптимальным с точки зрения удобочитаемости и простоты и, следовательно, с точки зрения ремонтопригодности. – twm 23 January 2018 в 20:51

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.');
5
ответ дан uKolka 19 August 2018 в 16:53
поделиться
  • 1
    Как ваш код имеет дело с объектами, которые ссылаются на себя? – jusio 7 May 2013 в 21:46
  • 2
    @jusio Привет, извините за задержку, не так много свободного времени. В этом конкретном случае речь не идет о собственных ссылках, а посмотрите на улучшенную версию . После немного большего количества тестов и обратной связи я отредактирую тот, что был в ответе. - uKolka – uKolka 21 May 2013 в 04:44
  • 3
    @jusio Вот более новая версия . Я обновил его для новых тестовых случаев. Это было неудачно, когда var a = {}, b = {}; a.self = a; b.self = {}; и в некоторых других случаях. – uKolka 21 May 2013 в 15:23
  • 4
    пожалуйста, не редактируйте прототипы объектов, которые у вас нет. – Umur Kontacı 1 July 2013 в 13:16
  • 5
    @Umur Kontacı Guilty. Я когда-нибудь обновлю его. – uKolka 1 July 2013 в 22:03

Если вы хотите проверить, что массивы объектов для равенства и порядка не имеют значения, то есть

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 не применяется к каждому массиву в первую очередь.

1
ответ дан willyhusted 19 August 2018 в 16:53
поделиться
6
ответ дан Community 31 October 2018 в 03:41
поделиться
27
ответ дан try-catch-finally 31 October 2018 в 03:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: