JavaScript:从字符串中删除原始和重复的字符

3
我需要的是删除原始字符及其重复项,不论其是小写还是大写。同时保留它是大写还是小写。
以下是我的当前代码,但它无法过滤大小写的字符串。
const removeDuplicateChar = s => s
  .split('')
  .filter( ( cur, index, self ) => self.lastIndexOf( cur ) === self.indexOf( cur ) )
  .join('')

实际输出

'services' becomes 'rvic'
'stress' becomes 'tre'
'ServicEs' becomes 'ServicEs'
'streSs' becomes 'treS'
'DeadSea' becomes 'DdS'

预期输出

'services' should be 'rvic'
'stress' should be 'tre'
'ServicEs' should also be 'rvic'
'streSs' should also be 'tre'
'DeadSea' becomes 'S'
6个回答

3

这样做会更快,因为循环中没有indexOf

const removeDuplicateChar = s => {
  let counts = Array.from(s.toLowerCase()).reduce(
    (counts, char) => counts.set(char, (counts.get(char) || 0) + 1) && counts,
    new Map());
  return Array.from(s).filter(letter =>
    counts.get(letter.toLowerCase()) == 1
  ).join('');
}

['services', 'stress', 'ServicEs', 'streSs', 'DeadSea'].forEach(word =>
  console.log(word, removeDuplicateChar(word))
)


2

.toLowerCase 的神奇之处

在进行检查时,你只需要使用 .toLowerCase ,但不要在此之前将其转换为小写字母,因为这将永久改变结果为全小写字母,这不是你想要的。

const toLowerCase = string => string.toLowerCase
removeDuplicateChar = s => s
  .split('')
  .filter((cur, index, self) => self.map(toLowerCase).lastIndexOf(cur.toLowerCase()) === self.map(toLowerCase).indexOf(cur.toLowerCase()))

虽然这是一个混乱的版本,但它能保留你的代码,因此你不需要改变太多。


是的,这个很好用。谢谢啊。不过如果可能的话,我可能仍然需要更易读的代码 :) - Riyenz

2

试试这个。

var str = "DeadSea";
var s = str.toLowerCase();
var arr = s.split("");
arr.forEach(a => {
    if (arr.indexOf(a) !== arr.lastIndexOf(a)) {
        str = str.replace(new RegExp(a, "gi"), "");
    }
});
console.log(str);

正则表达式用得不错 :D - Riyenz

1
你可以使用小写字母来查找小写字符串。

function unique(s) {
    var l = s.toLowerCase();
    return Array
        .from(s, c => l.indexOf(c.toLowerCase()) === l.lastIndexOf(c.toLowerCase()) ? c: '')
        .join('');
}

console.log(['services', 'stress', 'ServicEs', 'streSs', 'DeadSea'].map(unique));


像往常一样,天才般的表现。 - Jack jdeoel
@SalmanA,字符串是不可变的,因此它不会改变原始字符串。 - Nina Scholz
@NinaScholz 对不起,我当时没有清醒地思考。 - Salman A

1

回答为什么你的代码没有给出预期的输出:

indexOf() 使用严格相等比较(与 === 或三等号运算符使用的方法相同)将 searchElement 与数组的元素进行比较。

这使得 indexOf()区分大小写的

解决方案:

在执行 indexOf 之前,您需要对两个字符串的大小写进行规范化。

您可以创建一个类似于以下方法:

function indexOfCaseInsenstive(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();

  return a.indexOf(b);
}

function lastIndexOfCaseInsenstive(a, b) {
  a = a.toLowerCase();
  b = b.toLowerCase();

  return a.lastIndexOf(b);
}

或者在您的代码中使用 toLowerCase()

1
你需要比较字符实例的 lastIndexOfindexOf,并以 s 作为参考,这样就不需要使用 self 并将其连接成字符串了。
const filterDuplicateCharacters = s => s
  .split('')
  .filter((c) => s.toLowerCase().lastIndexOf(c.toLowerCase()) === 
             s.toLowerCase().indexOf(c.toLowerCase()))
  .join('')

很好地重复使用了初始参数中的变量,使其既紧凑又易读。 - Riyenz
为了简洁起见,这个函数相当慢。它对s中的所有元素计算了两次s.toLowerCase(),这是一个额外的开销,可以通过事先缓存这个不变的值来轻松减少。 - Gaurang Tandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接