Странное поведение при возврате char.pop () внутри .map () - PullRequest
2 голосов
/ 02 мая 2019

Проблема

Я создал (или попытался создать) функцию JS, которая переворачивает строку, игнорируя специальные символы .Функция не работает, если есть 2 последовательных специальных символа .

Код

Я предоставляю весь код, необходимый для воспроизведения проблемы ниже.включая некоторые тесты, которые вы можете запустить с mocha. Второй тест не пройден.

Следующий код проходит тесты:

const assert = require('assert');

const reverseButNoSpecial = (str) => {
    const specialChars = /[^a-zA-Z ]/g;

    // create an array withOUT special chars
    const cleanArray = str.replace(specialChars, "").split('');

    // iterate over the original
    // replace each letter with a letter from the clean array,
    // leave the special chars
    return str.split('').map(char => {
        if (specialChars.test(char)) {
            return char;
        }
        // remove the last char from the reversed array
        const removed = cleanArray.pop();
        // return the char that was removed
        return removed;
    }).join('');
}

describe('Reverse all characters except special chars', () => {
    it ('should work for a,b$c!', () => {
        expected = 'c,b$a!';
        actual = reverseButNoSpecial('a,b$c!');
        assert.strictEqual(expected, actual);
    })

    it ('should work for Ab,c,d$$e!', () => {
        expected = 'ed,c,b$$A!';
        actual = reverseButNoSpecial('Ab,c,d$$e!');
        assert.strictEqual(expected, actual);
    })
})

Ожидается против фактического

Ожидается reverseButNoSpecial('Ab,c,d$$e!') вернуть ed,c,b$$A! но получил ed,c,b$A!

(обратите внимание, что $ появляется только один раз, когда должно появиться дважды $$

Может кто-нибудь помочь мне выяснить, почему?

1 Ответ

2 голосов
/ 02 мая 2019

При повторном использовании объектов регулярного выражения, которые осуществляют поиск по всему миру, возникает проблема. Объекты регулярного выражения поддерживают состояние, в частности, свойство lastIndex остается неизменным.

Вот хорошее объяснение: https://siderite.blogspot.com/2011/11/careful-when-reusing-javascript-regexp.html

Чтобы исправить, не используйте объект 'specialChars', просто используйте объект регулярного выражения raw, например так:

(/ [^ a-zA-Z] / г) .test (символ)

...