Открыть список
Как стать автором
Обновить

Комментарии 14

В первой задаче берем в качестве примера строку, которая включает в себя emoji и смотрим, как с ней справляются оба ваших решения в сравнении с однострочником:


image


Это происходит, потому что ваш код не учитывает существование знаков вне BMP, которые кодируются суррогатными парами UTF-16, и адресует не codepoint-ы, а их UTF-16-кодированное представление.

Интересное замечание, не знал этого)
Но это не мои решения, а автора оригинальной статьи — у меня перевод)
Во второй задаче гораздо разумнее найти позиции небуквенных символов, разница между ними и будет длиной слов. Такой подход сэкономит и время и память. (мы же хотим это сделать оптимально, иначе вообще подобные легкие задачи решать интереса мало)

const re = /[^A-Za-zА-Яа-я]/g
const string = 'Моя удивительная строка'
let match, pos = 0, maxLength = 0 

while (re.exec(string + '.') !== null) {
  maxLength = Math.max(maxLength, re.lastIndex - pos - 1)
  pos = re.lastIndex
}

console.log('Длина самого длинного слова:' + maxLength)

Можно ускорить ваше решение, если искать не небуквенные символы, а места переходов от буквенных к небуквенным:


function longest(s) {
  const reStart = /(?:\W|^)\w/g;
  const reEnd = /\w(?:\W|$)/g;
  let inWord = false;
  let longest = 0;
  let startOffset;

  do {
    if (!inWord) {
      const m = reStart.exec(s);
      if (!m) {
        return longest;
      }
      reEnd.lastIndex = reStart.lastIndex - 1;
      startOffset = m.index - 2 + m[0].length;
      inWord = true;
    } else {
      const m = reEnd.exec(s);
      reStart.lastIndex = reEnd.lastIndex - 1;
      longest = Math.max(longest, m.index - startOffset);
      inWord = false;
    }
  } while (true);
};
Регулярки меня всё-таки сведут с ума)
Можете подсказать хорошие статьи по ним?
Возможно достаточно поменять выражение на
/[^A-Za-zА-Яа-я]+/g

но это будет извлекать ненужные участки междусловных знаков как строку, от чего мы вроде как хотели избавиться? :)
И, наверное, лучше использовать классы знаков — ваше выражение аналогично /\W+/g, но не считается с буквами других алфавитов.

Мы хотели избавиться от извлечения слов, но возможно вы правы, это лишнее

А Вы уверены, что регулярки в данном случае сэкономят время? Это довольно тяжелый инструмент. Я бы уж тогда сделал вот так


const string = 'Моя удивительная строка';
let pos = 0, max = 0;
for (const idx in string) { 
    if (string[idx] == ' ' || idx == string.length - 1) { 
        max = Math.max(max, idx - pos); 
        pos = idx; 
    }
}
Регулярку использовал просто для удобства, чтобы не писать

const l = string[idx]
if ((l < 'A' || l > 'Z') && 
       (l < 'a' || l > 'z') &&
       (l < 'А' || l > 'Я') &&
       (l < 'а' || l > 'я'))


Так да, возможно перебор будет немного быстрей.
В обоих случаях могут быть проблемы с «Ё»/«ё» (и это ещё без учёта некоторых других языков).
А знаки препинания?

Странно, что в примерах на поиск максимума в массивах не используется reduce. На мой взгляд это проще, чем map с… И вообще создавать дополнительные массивы для поиска максимума странно, если можно обойтись итераторами.

Вторая задача не учитывает пунктуацию. Можно сделать так:


image


Или, как вариант, не абюзить replace и запросить все матчи как-то так:


const allMatches = (s, re) => {
    const matches = [];
    let m;
    while (m = re.exec(s)) {
        matches.push(m[0]);
    }
    return matches;
}

Но мне кажется, что это проще сделать за один проход.

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