@alexbog90

Как сравнить символ с каждым символом из массива?

Задачка с codewars:

The goal of this exercise is to convert a string to a new string where each character in the new string is "(" if that character appears only once in the original string, or ")" if that character appears more than once in the original string. Ignore capitalization when determining if a character is a duplicate.
Examples
"din" => "((("
"recede" => "()()()"
"Success" => ")())())"
"(( @" => "))(("
Assertion messages may be unclear about what they display in some languages. If you read "...It Should encode XXX", the "XXX" is the expected result, not the input!

Есть решение, как проверить на схожесть символов, стоящих рядом друг с другом:
let string = "sqgdposq";
let splittedString, copyArray = [];
let convertString = function(string) {
  splittedString = string.split("");
  splittedString.forEach((element, index) => {
    if (splittedString[index] == splittedString[index+1] || splittedString[index] == splittedString[index-1]) {
        element = "1";
      } else {
        element = "2";
      }
      copyArray.push(element);
  });
  console.log(splittedString);
  console.log(copyArray);
}
convertString(string);


Как его изменить, чтобы каждый символ сравнивался с каждым символом из первоначального массива, а не только с ближайшим символом?
  • Вопрос задан
  • 2280 просмотров
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
Не надо сравнивать каждый с каждым, считайте количество повторений:

function duplicateEncode(str) {
  const arr = [...str.toLowerCase()];
  const count = arr.reduce((acc, n) => (acc[n] = (acc[n] || 0) + 1, acc), {});

  return arr.map(n => count[n] > 1 ? ')' : '(').join('');
}

Или не считайте:

function duplicateEncode(str) {
  const arr = str.toLowerCase().split('');
  const duplicates = arr.reduce((acc, n) => (acc[n] = acc.hasOwnProperty(n), acc), {});

  return ''.concat(...arr.map(n => '()'[+duplicates[n]]));
}

const duplicateEncode = str => Object
  .values(Object
    .values(str.toLowerCase())
    .reduce((acc, n, i) => ((acc[n] = acc[n] || []).push(i), acc), {}))
  .reduce((acc, n) => (n.forEach(i => acc[i] = n.length > 1 ? ')' : '('), acc), [])
  .join``;

const duplicateEncode = str => Array
  .from(str.toLowerCase())
  .reduce((acc, n, i, a) => acc + (a.indexOf(n) === a.lastIndexOf(n) ? '(' : ')'), '');

const duplicateEncode = str => str
  .toLowerCase()
  .replace(/./g, (m, _, s) => String.fromCharCode(40 + (s.split(m).length > 2)));
Ответ написан
Просто попробовал) Думаю вариант так себе, но на вскидку рабочий.
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
var sourceString = '(( @';

[...sourceString]
    .map(char =>
        (
            sourceString.match(
                RegExp(char.replace(reRegExpChar, '\\$&'), 'gi'),
            ) || []
        ).length <= 1
            ? '('
            : ')',
    )
    .join('');
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы