Уникальные строковые массивы javascript без учета регистра, но сохраняют один результат с учетом регистра

Что я имею в виду под этим? Сначала давайте посмотрим на код, который я написал:

  let names = ['James', 'james', 'bob', 'JaMeS', 'Bob'];
  let uNames = {};

  names.forEach(n => {
    let lower = n.toLowerCase();
    if (!uNames[lower]) {
      uNames[lower] = n;
    }
  });

  names = Object.values(uNames);
  console.log(names); // >>> (2) ["James", "bob"]

Целью здесь является уникальность заданного массива без учета регистра, но сохранение одного из исходных входных данных.

Мне было интересно, есть ли более элегантное / более эффективное решение этой проблемы, чем то, которое я придумал.

Простое преобразование всего массива в нижний регистр, прежде чем сделать его уникальным, не является решением, потому что я хотел бы, чтобы конечный результат состоял только из значений, которые уже были во входном массиве. Какой (например James или же james или же JaMeS) не актуально.

1 ответ

Решение

Мне было интересно, есть ли более элегантное / более эффективное решение этой проблемы, чем то, которое я придумал.

Использовать Map:

let names = ['James', 'james', 'bob', 'JaMeS', 'Bob'];
let uNames = new Map(names.map(s => [s.toLowerCase(), s]));

console.log([...uNames.values()]); 

Конструктор Map может принимать массив пар (вложенные массивы с двумя значениями: ключ и значение). Карта будет поддерживать уникальный список ключей, поэтому при ее создании ранее сохраненные значения будут перезаписаны, если ключ одинаковый.

Когда у вас есть карта, вы можете перебирать значения с помощью .values(),

Если вы хотите дедуплицировать массив строк с приоритетом для первых вхождений, сохраняя порядок вставки, используйте это.

const a = ["ALPHA", "10", "BETA", "10", "alpha", "beta", "aLphA"];
const b = ["3", "1", "2", "2", "3", "1"];

function dedupe(string_array) {
 const entries = string_array
  .slice()
  .reverse()
  .map((string, index) => [
   string.toLowerCase(),
   {
    string,
    index: string_array.length - 1 - index
   }
  ]);
 const case_insensitively_deduped_string_array = Array
  .from((new Map(entries)).values())
  .sort((a, b) => (a.index - b.index))
  .map(item => item.string);
 return case_insensitively_deduped_string_array;
 // Takes the first occurrences, keeping the insertion order.
 // Doesn’t modify the input array.
}

console.log(a, dedupe(a));
console.log(b, dedupe(b));

Другие вопросы по тегам