如何使用JavaScript从字符串中删除一个字符?

519

我离解决这个问题很近了,但还不完美。 我想做的仅是从一个字符串中移除字符r。 问题在于,字符串中有多个r实例。 然而,它总是位于索引4处(即第5个字符)。

示例字符串: crt/r2002_2

我想要的结果: crt/2002_2

下面这个replace函数会移除所有的r

mystring.replace(/r/g, '')

输出: ct/2002_2

我尝试了这个函数:

String.prototype.replaceAt = function (index, char) {
    return this.substr(0, index) + char + this.substr(index + char.length);
}
mystring.replaceAt(4, '')

如果我将其替换为另一个字符,它才会起作用。 它不会简单地将其删除。

有什么想法吗?


这里有什么问题,"r"都被删除了,不是吗? - Vladimir Despotovic
不,第一个不是。 - Capt 171
22个回答

651
var mystring = "crt/r2002_2";
mystring = mystring.replace('/r','/');

将使用 String.prototype.replace/r替换为/

或者你也可以像下面Erik ReppenSagar Gala建议的那样,使用带全局标志的正则表达式来替换所有出现的字符串。

mystring = mystring.replace(/\/r/g, '/');

编辑:鉴于大家在这里非常开心,而user1293504似乎不打算回来回答澄清问题,这里提供一种从字符串中删除第N个字符的方法:

String.prototype.removeCharAt = function (i) {
    var tmp = this.split(''); // convert to an array
    tmp.splice(i - 1 , 1); // remove 1 element from the array (adjusting for non-zero-indexed counts)
    return tmp.join(''); // reconstruct the string
}

console.log("crt/r2002_2".removeCharAt(4));

因为user1293504使用了正常计数而不是从零开始的计数,所以我们必须从索引中减去1,如果您希望使用此方法来复制charAt的工作原理,请勿在第三行从索引中减去1,并改用tmp.splice(i, 1)


4
第四个字符不一定是斜杠 "/" - jak.b
1
这个函数运行得很完美,只需要一个更正。我把 tmp.splice(i - 1 , 1); 改成了 tmp.splice(i , 1); - StevenJe

103

一种简单的功能性JavaScript方法是:

mystring = mystring.split('/r').join('/')

它简单易懂、快速,可以全局替换,不需要函数或原型。


3
这对我非常有效。当我尝试使用mystring = mystring.replace('/r','/');时,它只会转换第一个字符,其余的字符保持不变。 - VishnuPrasad
2
第四个字符不一定是 '/' - jak.b
1
无论如何,根据测试(https://dev59.com/ilUL5IYBdhLWcg3wWG9I),除非你正在编写高性能(每秒10k操作)的JavaScript,否则性能差异不是问题或“高昂的代价”,因此我不明白你的评论如何对解决方案有所贡献。 - Strife86
1
除了效率低下之外(而且这样的函数可能会在长列表上迭代使用,这很重要),这并没有回答 OP 的问题,因为它取决于索引,而不是前一个字符。 - aamarks

76

如果您知道要删除的始终是第四个字符,则可以使用字符串函数:

str.slice(0, 4) + str.slice(5, str.length)

当删除第一个或最后一个字符时,这将无效。 - TekTimmy
4
为什么不行?str.slice(0, 0) + str.slice(1, str.length)会移除第一个字符,而str.slice(0, str.length-1) + str.slice(str.length, str.length)则会移除最后一个字符。(当然,如果你知道你总是要移除第一个或最后一个字符,可以去掉冗余部分,但如果它们是变量,它们与任何其他索引一样有效。) - JJJ
2
末尾多了一个 ) - Srishti Gupta

34
你的第一个函数几乎是正确的。只需删除代表“全局”的'g'标志(编辑)并提供一些上下文来找到第二个'r'。
编辑:之前没有看到它是第二个'r',所以添加了'/'。在使用regEx参数时需要使用\/来转义'/'。感谢你们的支持,但我错了,所以我会修复并为那些有兴趣更好地理解正则表达式基础知识的人增加更多细节,但这将有效:
mystring.replace(/\/r/, '/')

现在开始进行冗长的解释:

在阅读/编写正则表达式模式时,请考虑以下方面:<一个字符或一组字符>后跟着<一个字符或一组字符>,再后跟着<...>。

在正则表达式中,<一个字符或一组字符>可以是一个一个地定义:

/each char in this pattern/

读作e,然后是a,然后是c等等...

或者单个的<a字符或一组字符>可以被描述为字符类:

/[123!y]/
//any one of these
/[^123!y]/
//anything but one of the chars following '^' (very useful/performance enhancing btw)
或者可以扩展到匹配一定数量的字符(但在顺序模式方面仍然最好将其视为单个元素):
/a{2}/
//precisely two 'a' chars - matches identically as /aa/ would

/[aA]{1,3}/
//1-3 matches of 'a' or 'A'

/[a-zA-Z]+/
//one or more matches of any letter in the alphabet upper and lower
//'-' denotes a sequence in a character class

/[0-9]*/
//0 to any number of matches of any decimal character (/\d*/ would also work)

将它们挤在一起:

   var rePattern = /[aA]{4,8}(Eat at Joes|Joes all you can eat)[0-5]+/g
   var joesStr = 'aaaAAAaaEat at Joes123454321 or maybe aAaAJoes all you can   eat098765';

   joesStr.match(rePattern);

   //returns ["aaaAAAaaEat at Joes123454321", "aAaAJoes all you can eat0"]
   //without the 'g' after the closing '/' it would just stop at the first   match and return:
   //["aaaAAAaaEat at Joes123454321"]
当然,我过于详细了,但我的意思只是这个:
/cat/

这是一系列由3个模式元素组成的序列(一个事物跟随着另一个事物,再跟随着另一个事物)。

这也是如此:

/[aA]{4,8}(Eat at Joes|Joes all you can eat)[0-5]+/

尽管正则表达式看起来很奇怪,但本质上它们都可以分解为按顺序依次跟随的一系列(可能是多个字符的)元素。这是一个基本点,但我花了很长时间才理解它,所以我在这里进行了过度解释,因为我认为这会帮助提问者和其他新手更好地理解正则表达式中发生的事情。阅读/编写正则表达式的关键是将其分解成这些部分。


19

只需要修复你的replaceAt函数:

String.prototype.replaceAt = function(index, charcount) {
  return this.substr(0, index) + this.substr(index + charcount);
}

mystring.replaceAt(4, 1);

我会将它称为removeAt。 :)


16

对于全局替换'/r',这段代码对我有用。

mystring = mystring.replace(/\/r/g,'');

11

这是对simpleigh回答的改进(省略长度)。

s.slice(0, 4) + s.slice(5)

let s = "crt/r2002_2";
let o = s.slice(0, 4) + s.slice(5);
let delAtIdx = (s, i) => s.slice(0, i) + s.slice(i + 1); // this function remove letter at index i

console.log(o);
console.log(delAtIdx(s, 4));


当与.substring(start,end)配对以获取子字符串,然后删除子字符串时,这是最直接的方法。 - franklylately

8

let str = '1234567';
let index = 3;
str = str.substring(0, index) + str.substring(index + 1);
console.log(str) // 123567 - number "4" under index "3" is removed


7
return this.substr(0, index) + char + this.substr(index + char.length);

char.length为零。在这种情况下,您需要添加1以跳过字符。


这并没有回答所提出的问题,只是解释了为什么 replaceAt 不起作用。它应该是原始问题的评论,而不是答案。 :) - Ken White
@KenWhite,实际上它确实回答了唯一提出的问题,“有什么想法?” - Ash Burlaczenko
好的,我不同意,但是... :) 我没有投反对票,但我认为这并不符合答案的要求。一个答案应该提供解决问题的方案,或者至少用更多的细节来解释并提供修复的想法。 - Ken White
@KenWhite,我同意,我只是想指出OP可能需要更清晰地表达他的问题?有些人只是想知道方向,而不是直接得到答案。 - Ash Burlaczenko
1
+1 给 @paislee - 这个答案并不有用,因为在 JavaScript 中没有 char 这个东西。 - simpleigh
char是OP的参数名称!这个答案解决了问题:使用1代替char.length。OP的函数最初编写得很糟糕,因为OP总是想在索引处删除一个字符。它永远不应该将replacement.length作为开始保留尾部字符串的因素。 - aamarks

6
也许我是个新手,但今天我遇到了这些问题,它们似乎都过于复杂。 以下是我认为更简单的方法来从字符串中删除任何你想要删除的东西。
function removeForbiddenCharacters(input) {
let forbiddenChars = ['/', '?', '&','=','.','"']

for (let char of forbiddenChars){
    input = input.split(char).join('');
}
return input

}


1
虽然您可能认为这个解决方案更简单,而其他方案则是“不必要的复杂”,但由于重复的字符串拆分和连接(这将导致过多的新字符串分配和复制),此解决方案的运行时性能较差。我在这个基准测试中将您的解决方案与单个.replaceAll调用进行了比较(https://jsben.ch/AAGDc),结果发现`replaceAll`快96%。 - Dai

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