Метод JavaScript для удаления нечувствительных к регистру дубликатов из строки / чисел - PullRequest
0 голосов
/ 08 мая 2019

Ищите чистый способ удаления дубликатов и сохраняйте их при первом появлении найденного дубликата / буквы

Допустим, у меня есть строка

AbCyTtaCc113

То, что я хочу, это

AbCyT13

Ответы [ 4 ]

4 голосов
/ 09 мая 2019
  [...input].filter((s => c => !s.has(c.toLowerCase()) && s.add(c.toLowerCase()))(new Set)).join("")

Распределение строки приводит к массиву с одной строкой символов, с помощью Set вы можете легко отфильтровать дубликаты. Логика в основном:

  • Превратить строку в массив символов, расширив ее ([...input]).

  • Создайте набор и сохраните его в закрытии как s. ((s => ...)(new Set))

  • Отфильтровать символы, если

    • персонаж уже в наборе (!s.has(c.toLowerCase())

    • , если это не так, добавьте его в набор и сохраните (&& s.add(c.toLowerCase()))

  • Превратите отфильтрованный массив обратно в строку, соединив ее.

Или версия без учета регистра:

[...new Set(input)].join("")

Императивная версия будет:

  let result = "";
  {
     const duplicates = new Set();
     for(const char of input) {
        if(!duplicates.has(char.toLowerCase()) {
          duplicates.add(char.toLowerCase());
          result += char;
        }
     }
  }
0 голосов
/ 09 мая 2019

для этого не нужен ES6, он не делает его быстрее и чище для этого случая.Пройдите по нему один раз и уменьшите:

"AbCyTtaCc113"
.split("")
.reduce((ac,d)=>{!~ac.toLowerCase().indexOf(d.toLowerCase()) && (ac += d); return ac;},"")
0 голосов
/ 09 мая 2019

Я считаю, что @ggorlen имеет подходящее решение, хотя он использует довольно современный JavaScript (я не видел синтаксиса до использования обратных тиков вместо скобок для вызова функций, но я верю, что это работает в некоторых интерпретаторах)

Для более простого ответа «старой школы» попробуйте что-то вроде следующего:

var input = "AbCyTtaCc113";
var output = "";
var unique = {};
for (var i = 0; i < input.length; i++) {
    if (!unique[input[i].toLowerCase()]) {
        unique[input[i].toLowerCase()] = 1;
        output += input[i];
    }
}

Второе обновление

Приведенное ниже решение ES6 было сохранено для исторических целей, но@ggorlen указал, что мне не удалось сохранить корпус на выходе.Поэтому преобразование в нижний регистр должно происходить только при проверке фильтра, а не ранее:

var input = "AbCyTtaCc113";
var seen = new Set();
var output = input
    .split("")
    .filter(x => !seen.has(x.toLowerCase()) && seen.add(x.toLowerCase()))
    .join("")

Обновление

Поскольку всем нравится писать ответы на ES6 и пытаться решить эту проблему с помощью reduce илиmap или Set или какой-либо другой подобный инструмент, позвольте мне написать, как я думаю, ответ лучший с использованием ES6:

var input = "AbCyTtaCc113";
var seen = new Set();
var output = input
    .split("")
    .map(x => x.toLowerCase())
    .filter(x => !seen.has(x) && seen.add(x))
    .join("")

Или, есливы предпочитаете нечитаемую чепуху в одну строку:

var input = "AbCyTtaCc113";

var seen = new Set(), output = input.split("").map(x => x.toLowerCase()).filter(x => !seen.has(x) && seen.add(x)).join("");

Я предпочитаю это решение, потому что:

  1. В нем используется цепочка методов для передачи нашего ввода через ряд простых преобразований, которые легкочитать и интерпретировать будущие программисты (сначала разделить, затем отобразить, затем отфильтровать, затем объединить)
  2. Избегает синтаксиса, который не поддерживается во многих интерпретаторах JavaScript (без операторов распространения, обратных тиков и т. д.)
  3. Он использует каждый метод для своей семантической цели (split преобразует строку в массив, map изменяет каждое значение массива, фильтр выбирает подмножество массива, join преобразовывает массив в строку)

Тем не менее, если производительность является вашей главной задачей, и вы запускаете ее в консоли Google Chrome, я должен признать, что предварительные тесты оценивают ответ Джонаса Вильма как более быстрый, чем мой:

var d0 = new Date(); for (var i = 0; i < 50000; i++) {
    var input = "AbCyTtaCc113";
    var output = [...input].filter((s => c => !s.has(c.toLowerCase()) && s.add(c.toLowerCase()))(new Set)).join("");
} console.log(new Date() - d0);
// ~175

var d0 = new Date(); for (var i = 0; i < 50000; i++) {
    var input = "AbCyTtaCc113";
    var seen = new Set();
    var output = input
        .split("")
        .map(x => x.toLowerCase())
        .filter(x => !seen.has(x) && seen.add(x))
        .join("");
} console.log(new Date() - d0);
// ~231

Я полагаю, это потому, что .map() выделяет новый массив в памяти, а не модифицирует массив на месте (тогда как его решение, использующее .toLowerCase() в .has(), изменяет значения на месте, поэтому не использует дополнительную память), но я предпочитаю это для ясности.Если вы не имеете дело с кодом, где производительность имеет первостепенное значение, я думаю, что возможность читать код важнее, чем выделять лишнюю миллисекунду.

0 голосов
/ 09 мая 2019

Использование Array.prototype.reduce будет одним из способов решения этой проблемы.

Редактировать: Как уже упоминали другие, есть веские причины, хотя и не использовать это для решений производственного уровня. Поэтому просто примите это как один возможный , но не рекомендуемый способ.

console.log(
  [..."AbCyTtaCc113"]
    .reduce(
      (acc, val) => 
        acc.includes(val.toUpperCase()) || acc.includes(val.toLowerCase())
          ? acc 
          : [...acc, val]
        , []
    )
    .join("")
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...