javascript唯一字符串数组不区分大小写,但保留一个区分大小写的结果

Tob*_*rth 1 javascript arrays performance unique case-insensitive

我是什么意思?首先让我们看看我写的一些代码:

  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"]
Run Code Online (Sandbox Code Playgroud)

这里的目标是使给定的数组不区分大小写,但保留原始输入之一。

我想知道是否有比我想出的解决方案更优雅/性能更好的解决方案。

在使其唯一之前将整个数组转换为小写不是解决方案,因为我希望最终结果仅包含输入数组中已有的值。哪个(例如JamesjamesJaMeS)不相关。

tri*_*cot 7

我想知道是否有比我想出的解决方案更优雅/性能更好的解决方案。

使用Map

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

console.log([...uNames.values()]); 
Run Code Online (Sandbox Code Playgroud)

的构造函数Map可以采用一对数组(具有 2 个值的嵌套数组:键和值)。Map 将维护一个唯一的键列表,因此在构造它时,如果键相同,则先前存储的值将被覆盖。

拥有 Map 后,您可以使用 迭代这些值.values()

用普通对象

您还可以使用该Object.fromEntries方法,在撰写本文时,该方法是在 Chrome、Firefox、Opera 和 Safari 中实现的第 4 阶段提案(草案 ES2020):

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

console.log(Object.values(uNames)); 
Run Code Online (Sandbox Code Playgroud)

如您所见,该方法非常相似。

第一次出现和原始顺序

以上将收集最后一次出现,按第一次出现的顺序。

如果您想收集第一次出现,您可以先反转输入,然后继续如上。然后输出将按照最后一次出现的顺序收集一次出现。

如果您确实需要按第一次出现的顺序第一次出现,您可以使用reduce如下:

let names = ['James', 'james', 'bob', 'JaMeS', 'Bob'];
let uNames = names.map(s => s.toLowerCase()).reduce((map, s, i) => 
    map.get(s) ? map : map.set(s, names[i])
, new Map);

console.log([...uNames.values()]); 
Run Code Online (Sandbox Code Playgroud)