Сравнение значений между двумя массивами

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

function palindrome(str) {
  var low = str.toLowerCase();
  var newArray = low.split("");
  var noSpace = newArray.filter(function(val) {
    return val !== " ";
  });
  var reverse = noSpace.reverse();
  
  function check (a, b) {
    console.log(`checking '${a}' against '${b}'`);
    var partial;
    var result = 1;
    for (var i = 0; i < a.length; i++) {
      console.log(`comparing '${a[i]}' and '${b[i]}'`);
      if (a[i] !== b[i]) {
        result = 0;
      } else {
        partial = 1;
        result *= partial;
      }
    }
    return result;
  }
  
  var result = check(noSpace, reverse);
  if (result == 1) {
    return true;
  } else {
    return false;
  }
  
   
}


palindrome("r y e");

Я не знаю, что не так, но кажется, что функция продолжает возвращать истинное значение независимо от того, какое слово или текст я передаю функции. Что не так с этим?


person Dema    schedule 18.08.2017    source источник
comment
вы также можете указать название языка, который вы используете.   -  person Marcin Orlowski    schedule 18.08.2017
comment
Возможно, вы захотите правильно сделать отступ в своем коде. Чтобы отладить свой код, проходите его построчно с помощью отладчика, исследуя переменные по ходу дела.   -  person    schedule 18.08.2017
comment
Внимательно прочтите документацию для reverse real.   -  person    schedule 18.08.2017
comment
А что насчет мадам, я Адам?   -  person    schedule 18.08.2017
comment
Про забвение toLowerCase, да. Что касается запятой и апострофа, это тоже не то, что распознает код OP, и я не слишком уверен, что должно быть палиндромом. Строки могут содержать всевозможные странные символы, а также всевозможные странные знаки препинания. Первое, что приходит на ум, это , это пунктуация или часть предупреждения? 〜んん палиндром? Дополнение: исходя из вопроса, который я прочитал вчера, есть GREEK SMALL LETTER FINAL SIGMA' (U+03C2), при изменении этого значения вы превращаете его в обычную сигму, чтобы представить, что она больше не находится в конце строки?   -  person ASDFGerte    schedule 18.08.2017
comment
@ASDFGerte Попробуйте "????".split('').reverse().join('').   -  person    schedule 18.08.2017
comment
Да, можно также написать код, который разбивается на точки кода, а затем модификаторы, текст zalgo и все, что приходит, и вопрос расходится на миллиард вопросов о том, что вы хотите сделать? и 100% всех опубликованных ответов будут неправильными. Имхо, лучше всего было бы взять только ASCII и установить правила пунктуации, найденные в ASCII, что, по крайней мере, означало бы, что желаемый результат ясен.   -  person ASDFGerte    schedule 18.08.2017
comment
@ASDFGerte Да и нет. Если проблема заключается просто в обработке всех символов Юникода, включая дополнительные плоские символы, то все, что вам нужно, это [..."????"].reverse().join('').   -  person    schedule 18.08.2017
comment
@torazaburo Как уже было сказано выше, "ΣΣ".toLowerCase();. Отказ от ASCII откроет множество вопросов о том, каким должен быть палиндром. Реверсирование текста и модификаторов zalgo - это то, что я вижу, также не обрабатывается вашим примером.   -  person ASDFGerte    schedule 18.08.2017


Ответы (5)


Кажется, ваша проблема связана с изменениями reverse() фактический массив. Так поступаем

var reverse = noSpace.reverse();

Обратит noSpace и назначит ссылку на него в переменной reverse. То есть оба массива будут одним и тем же (перевернутым) массивом.

Чтобы обойти это, я использовал .slice() для создания копии исходного массива, а затем вызвал .reverse() для этого нового массива , избавляя вас от любых конфликтов.

Вот рабочий фрагмент того, как это выглядит:

function palindrome(str) {
    var str_array = str.toLowerCase().split("");
    var no_space = str_array.filter(function(val) {
        return val !== " ";
    });

    // By applying '.slice()', we create a new array
    // reference which can then be reversed and assigned
    // to the 'reverse' variable
    var reverse = no_space.slice().reverse();

    function check(a, b) {
        var partial;
        var result = 1;
        for(var i=0; i < a.length; i++) {
            if(a[i] !== b[i]) {
                // We don't need to keep
                // comparing the two, it
                // already failed
                return 0;
            } else {
                // I've kept this part even though
                // I don't really know what it is
                // intended for
                partial = 1;
                result *= partial;
            }
        }
        return result;
    }
    return check(no_space, reverse) === 1;
}

console.log(palindrome("a b a"));
console.log(palindrome("r y e"));

person Matheus Avellar    schedule 18.08.2017
comment
Похоже, что reverse () испортил мой код. slice () кажется хорошим решением. Я не получаю 'return check (no_space, reverse) === 1;' в конце функции палиндрома. Не могли бы вы мне это объяснить? - person Dema; 18.08.2017
comment
Функция check() вернет значение (0 или 1). Мы хотим, чтобы функция palindrome() возвращала либо true, либо false. Для этого нам нужно, чтобы значение, которое возвращает check(), сравнивалось с 0 или 1 (в данном случае с 1). Итак, если check() возвращает 1, мы получаем 1 === 1 (что равно true). Если check() возвращает 0, мы получаем 0 === 1 (что равно false). Таким образом, у нас есть palindrome(), возвращающий true или false в зависимости от возвращаемого значения функции check(). - person Matheus Avellar; 18.08.2017
comment
В качестве альтернативы вы можете сделать if(check(no_space,reverse)===1) { return true; } else { return false; }. Они оба будут работать одинаково, это просто вопрос размера кода. - person Matheus Avellar; 18.08.2017

То, как вы закодировали палиндром, слишком сложно.

Но с вашим кодом есть одна проблема: когда вы выполняете reverse(), он также изменяет исходный массив.

Поэтому вам нужно будет убедиться, что вы скопировали его через slice().

Также вы можете напрямую отправить логический результат, а не выполнять 1 и 0.

person Pritam Banerjee    schedule 18.08.2017

В result *= partial; 1 * 1 всегда будет равно 1

person guest271314    schedule 18.08.2017
comment
Но если result ранее был установлен в 0 из-за несоответствия, он останется 0. - person ; 18.08.2017
comment
@torazaburo Да, вы хотите сказать, что проблема в .reverse()? Почему вы не отправляете ответ? - person guest271314; 18.08.2017
comment
Я хотел, чтобы цикл for сравнивал все значения двух массивов, поэтому я подумал, что могу создать переменную, в которой будут храниться результаты всех сравнений. 1 совпадает с логическим значением true, поэтому я подумал, что могу его использовать. - person Dema; 18.08.2017
comment
@Dema Почему вы не используете result = 1? - person guest271314; 18.08.2017
comment
Мне нужна переменная, которая отслеживает предыдущие сравнения. Если я просто использую result = 1, но в какой-то момент в двух массивах два значения не совпадают, функция все равно вернет true, даже если слово не является палиндромом. Это верно? - person Dema; 18.08.2017
comment
Если ожидается, что result будет 0 или 1, какова цель оператора *=? - person guest271314; 18.08.2017

Я не исправлял ваш код, но вот вам оптимизированное решение.

function palindrom(string) {
    var arr = string.split("");

    var lengthToCheck = Math.floor(arr.length / 2);
    for (var i = 0; i < lengthToCheck; i++) {
        if (arr[i] != arr[arr.length - (1 + i)]) {
            return false;
        }
    }

    return true;
}

Сначала я разбиваю массив после каждого символа переданной строки. После этого я получаю половину длины массива, так как достаточно проверить только половину. С помощью цикла for я сравниваю первую половину со второй половиной. Как только я обнаружил два не совпадающих символа, я возвращаю false. В случае, если вся первая половина соответствует второй половине массива, цикл for будет завершен, и после этого будет возвращено значение true.

person Swittmann    schedule 18.08.2017
comment
Он / она не просил о новой реализации. В мире существует миллион реализаций палиндрома. Он / она спросил, почему опубликованный код не работает. - person ; 18.08.2017

На самом деле происходит .reverse() реверсирование массива на месте, а затем сохранение ссылки на этот массив, который не является тем, что вы вызываете в своем check() методе.

Простое исправление - изменить оператор if:

if (a[i] !== b.reverse()[i])
person Ricktron3000    schedule 18.08.2017
comment
Но разве это не будет реверсировать b на каждой итерации? - person Matheus Avellar; 18.08.2017
comment
Он работает случайно и очень неэффективно, меняя местами массив при каждом сравнении отдельных символов. - person ; 18.08.2017
comment
@torazaburo Согласовано, супер неэффективно и взломано. - person Ricktron3000; 18.08.2017