寻找一种干净的方法来删除重复项,并与发现的重复编号/字母的第一次出现保持一致
假设我有一个字符串
AbCyTtaCc113
我想要剩下的是
AbCyT13
答案 0 :(得分:4)
[...input].filter((s => c => !s.has(c.toLowerCase()) && s.add(c.toLowerCase()))(new Set)).join("")
散布字符串会导致一个包含一个字符串的数组,通过使用Set,您可以轻松过滤出重复项。逻辑基本上是:
通过扩展([...input]
)将字符串转换为字符数组。
创建一个Set并将其作为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;
}
}
}
答案 1 :(得分:0)
这不需要ES6,在这种情况下,它不会使其更快,也不会更干净。走路一次并减少:
"AbCyTtaCc113"
.split("")
.reduce((ac,d)=>{!~ac.toLowerCase().indexOf(d.toLowerCase()) && (ac += d); return ac;},"")
答案 2 :(得分:-1)
使用Array.prototype.reduce
是解决此问题的一种方法。
编辑:正如其他人所提到的,虽然没有将其用于生产级解决方案,但有充分的理由。因此,将其作为一种可能,尽管不是明智的方式。
console.log(
[..."AbCyTtaCc113"]
.reduce(
(acc, val) =>
acc.includes(val.toUpperCase()) || acc.includes(val.toLowerCase())
? acc
: [...acc, val]
, []
)
.join("")
)
答案 3 :(得分:-1)
我相信@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
或其他类似工具来解决这个问题,所以让我写一下我认为的 最佳 答案:
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("");
我更喜欢这种解决方案,因为:
也就是说,如果性能是您最关心的问题,并且您正在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()
的解决方案修改了这些值,因此不使用额外的内存),但是为了清楚起见,我更喜欢这样做。除非您要处理性能是最重要的代码,否则我认为能够读取代码比花费额外的毫秒时间更重要。