Уникальные строковые массивы 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));