Неожиданный возврат Javascript .reduce Boolean

Попытка создать функцию для проверки длинного числа (т. е. каждая цифра меньше или равна цифре справа от нее, например 123, 059 и т. д.).

Следующий код является проблемой:

const n = parseInt(readline());
if (n.toString().length === 1)
    console.log('true');
else
{
    var z = n.toString().split('');
    console.log(z.reduce((a, b) => b > a));
}

Этот тест не пройден: 01223047 (возвращает true, когда должен возвращать false).

Он работал во многих других тестах, но не в этом значении. Не должен ли reduce проверять каждую пару и возвращать true/false? Если есть одна ложь, она должна вернуть ложь, верно? Я неправильно использую сокращение? Есть ли другая функция, которую я мог бы использовать для сокращения этого теста вместо написания цикла?


person Arcaster    schedule 18.03.2019    source источник
comment
01223047 - это 337447 как целое число, вам нужно иметь n в виде строки и анализировать их в int в вашей функции сокращения   -  person George    schedule 18.03.2019
comment
а еще: у тебя брекеты какие-то странные...   -  person mb21    schedule 18.03.2019
comment
Кажется странным анализировать строку из readline только для того, чтобы затем неоднократно преобразовывать ее обратно в строку... Это особенно странно, если в одном из ваших примеров есть ведущая цифра 0, поскольку при этом удаляется ведущая цифра.   -  person T.J. Crowder    schedule 18.03.2019


Ответы (1)


Помните, что с reduce первым аргументом, переданным вашему обратному вызову, является возвращаемое значение предыдущего вызова обратного вызова. (В первом вызове, если вы не указали начальное значение и у вас нет первого значения, оно будет первой записью в массиве.)

Так что нет, этот reduce не проверяет каждую пару. Он проверяет первую пару, а затем проверяет остальные значения (по отдельности) на соответствие флагу, возвращенному предыдущим обратным вызовом.

Для того, что вы делаете, вам, вероятно, нужен простой цикл или some или every (вероятно, every). С some и every вы должны использовать индекс, предоставленный в качестве второго аргумента для обратного вызова, чтобы получить следующий (или предыдущий) символ. Использование every также устранит особый случай для односимвольной строки:

function test(str, expect) {
    const z = str.split(""); // I'd probably use `= Array.from(str);` on ES2015+
    const result = z.every((ch, i) => i === 0 || ch > z[i - 1]);
    console.log(str, result, !result === !expect ? "Good" : "ERRROR");
}


test("123", true);
test("1", true);
test("21", false);

(Возможно, есть аргумент в пользу использования localCompare в этом: ch.localeCompare(z[i - 1]) > 0 вместо ch > z[i - 1].)

person T.J. Crowder    schedule 18.03.2019
comment
Ударь меня! :D - person Jamie Dixon; 18.03.2019
comment
Интересно, что есть еще один способ взглянуть на эту проблему через призму комбинаторики. Сколько существует комбинаций этих цифр, где каждая цифра больше или равна цифре слева от нее? Есть только 1 возможная комбинация! Это означает, что мы в основном проверяем порядок сортировки: - person Jamie Dixon; 18.03.2019
comment
``` const isTall = n =› { const arr = (''+n).split(''); возврат arr === arr.sort(); } ``` - person Jamie Dixon; 18.03.2019
comment
@JamieDixon - :-) Совершенно верно. (Вы захотите преобразовать эти массивы обратно в строки для проверки ===.) - person T.J. Crowder; 18.03.2019
comment
Ага! Это также напомнило мне, что sort мутативен. Мне было интересно, почему ['b', 'a'] === ['a', 'b'] всегда возвращал true :) - person Jamie Dixon; 18.03.2019