783

我有一根绳子你好,世界,我需要替换索引3处的字符。如何通过指定索引来替换字符?

var str=“hello world”;

我需要这样的东西

str.replaceAt(0,“h”);
4
  • 262
    奇怪的是str[0]=“x”似乎没有抛出任何错误,但没有达到预期的效果!
    – 迈克尔
    评论 2013年11月15日19:43
  • 9
    @Michael这样,您将在0处获得索引,将其设置为“x”,语句本身将返回新值x’。但所有这些都没有改变原点,所以它完全有效,只是与你预期的不一样。它不是参考 评论 2013年11月21日14:46
  • 18
    @Michael如果“使用严格”已激活:Uncaught TypeError:无法分配给字符串“hello world”的只读属性“0”(至少在webkit浏览器中) 评论 2016年10月27日20:15
  • 10
    Javascript字符串是不可变的,不能“就地”修改,因此不能修改单个字符。事实上,同一字符串的每次出现都是一个对象。 评论 2019年5月7日20:33

30个答案30

重置为默认值
850

在JavaScript中,字符串是不可变的,这意味着您所能做的最好的事情就是使用更改的内容创建一个新字符串,并将变量指定给它。

您需要定义替换At()发挥自己的作用:

String.prototype.replaceAt=函数(索引,替换){返回this.substring(0,index)+replacement+this.substring(index+replacement.length);}

并按如下方式使用:

var hello=“hello World”;alert(hello.replaceAt(2,“!!”);//他!!o世界
23
  • 188
    注意,扩展基本JavaScript类通常不是一个好主意。请改用普通实用程序函数。 评论 2009年9月16日5:40
  • 102
    我必须问为什么?为此,提供了原型支持。 评论 2009年9月16日6:58
  • 42
    @CemKalyoncu:它可以使代码在其他库中不起作用。但我自己从来没有被咬过。 评论 2011年7月21日4:53
  • 9
    @亚历克斯:你说得对,你真的需要在执行之前检查这个函数是否存在。但即使存在,它也应该执行完全相同的操作。 评论 2011年7月21日10:11
  • 114
    我不同意,即使您检测到该函数是否存在,以后的库可能仍会使用/创建类似的函数——两个坏主意会使一个更坏。一般来说,永远不要玩弄其他人的代码(包括核心系统)。创建新函数。
    – 马蒂曼
    评论 2012年6月5日1:05
164

没有替换时间JavaScript中的函数。您可以使用以下代码替换指定位置的任何字符串中的任何字符:

函数rep(){var str='Hello World';str=setCharAt(str,4,'a');警报(str);}函数setCharAt(str,index,chr){如果(index>str.length-1)返回str;返回str.substring(0,index)+chr+str.substrang(index+1);}
单击

4
  • 我更喜欢这个解决方案,因为你可以用它替换单个字符。如果你只想替换一个字符,那么支持票最多的解决方案是行不通的。它只在替换两个字符时有效!此外,如许多其他注释中所述,应该用子字符串替换子字符串。
    – 千兆努
    评论 2020年1月14日11:31
  • 1
    在我的测试中,这种方法是目前为止最快的。。。如果不需要验证[index]不大于字符串长度,则速度更快。被改进的:函数setCharAt(str,idx,newChr){return str.substring(0,idx)+newChr+str.substrang(idx+1);} 评论 2020年9月10日7:09
  • 1
    @斯科特斯勒-这个答案使用子串,不是子(substr)……在你的链接中,它在哪里说这两种功能是“遗留”的还是应该避免的。。。子串子(substr)服务不同的目的. 评论 2020年9月10日7:13
  • @ashleedawg看起来它不再被弃用了。 评论 2020年9月11日20:46
129

不能。将位置前后的字符连接成新字符串:

var s=“Hello world”;var指数=3;s=s.substring(0,索引)+“x”+s.substring(索引+1);
  • 事实上,是的,你可以,但这太过分了。您可以设置一个正则表达式来跳过第一个索引-1字符,并匹配索引处的字符。您可以将String.replace与该正则表达式一起使用,以进行直接的就地替换。但这太过分了。所以,在实践中你不能。但在理论上,你可以。 评论 2009年9月16日5:42
  • 16
    @Ates:replace函数不进行就地替换,它创建一个新字符串并返回它。 评论 2009年9月16日5:55
  • 4
    MDN公司建议使用字符串.原型.子字符串结束字符串.原型.子字符串. 评论 2019年2月10日11:55
81
str=str.split(“”);str[3]=“h”;str=str.join(“”);
8
  • 9
    清晰简单,但目前无法使用表情符号(例如😀) 使用时分裂参加
    – 绿色
    评论 2016年6月26日10:15
  • 4
    对于es6,我认为Array.from(str)现在可能是一个更好的选择,但我带着这些知识来到这里,从您那里学到了一些同样简明扼要的东西,所以谢谢! 评论 2018年6月23日3:23
  • 1
    @戴维·卡默我去派对迟到了,但看起来阵列起始位置明显慢于str.split街.blog.shovonhasan.com/…
    – 查尔斯
    评论 2021年10月8日12:05
  • @如果字符串包含表情符号,则为绿色,这可能是用户输入,因此我认为没有明显的理由使用此方法更改字符串中的字符,如果要更改输入转换场景中的某个部分,则应使用代替方法。 评论 2022年3月24日10:47
  • 1
    @KadenSkinner这是一个数组,所以你可以str.splice(3,h.length,…h.split(“”))str.splice.apply(str,[3,h.length].concat(h.split('')))但与之相比,这似乎有些疯狂str.substring(0,3)+h+str.substrang(5).
    – 夹头
    评论 2022年4月7日18:27
37

这里有很多答案,所有答案都基于两种方法:

  • 方法1:使用两个子字符串拆分字符串,并在它们之间填充字符
  • METHOD2:将字符串转换为字符数组,替换一个数组成员并将其联接

就个人而言,我会在不同的情况下使用这两种方法。让我解释一下。

@FabioPhms:你的方法是我最初使用的方法,我担心它对包含大量字符的字符串不好。然而,问题是什么是许多字符?我在10个“lorem ipsum”段落上进行了测试,花费了几毫秒。然后我在10倍大的绳子上测试了它——真的没有太大的差别。嗯。

@vsync,@Cory Mawhoter:你的评论很明确;然而,再说一遍,什么是大字符串?我同意,对于32…100kb的性能应该更好,对于这一个字符替换操作,应该使用子字符串变量。

但是,如果我必须更换一些,会发生什么呢?

我需要自己进行测试,以证明在这种情况下什么更快。比方说,我们有一个算法可以处理由1000个字符组成的相对较短的字符串。我们预计该字符串中的每个字符平均将被替换约100次。因此,测试这样东西的代码是:

var str=“…{此处有一个大字符串}…”;对于(var i=0;i<100000;i++){var n=''+数学地板(Math.random()*10);var p=数学地板(Math.random()*1000);//替换位置*p上的字符*n**}

我为此制作了一把小提琴在这里.有两个测试,TEST1(子字符串)和TEST2(数组转换)。

结果:

  • 测试1:195ms
  • 测试2:6ms

看起来数组转换比子串快2个数量级!那么,这里到底发生了什么???

实际上,TEST2中的所有操作都是在数组本身上完成的,使用的赋值表达式如下strarr2[p]=n。与大字符串上的子字符串相比,赋值真的很快,很明显它会赢。

所以,这一切都是为了选择适合这份工作的工具。再一次。

10
  • 8
    将测试转移到jsperf,结果大不相同:jsperf.com/string-replace-character。关键是为工作选择合适的工具;)
    – 夹头
    评论 2014年10月30日3:11
  • 1
    @科林:我完全同意。因此,我几乎完全将测试从jsfiddle克隆到了jsperf。然而,除了使用正确的工具外,还必须以正确的方式进行。注意这个问题,我们正在讨论如果我们必须在一个算法中进行相当多的替换,将会发生什么。具体示例包括10000个替换。这意味着一次测试应包括10000个更换件。因此,使用jsperf,我得到了非常一致的结果,请参见:jsperf.com/…. 评论 2014年10月30日9:22
  • 1
    这就是我不喜欢javascript的原因。如此频繁、直观、明显的用例是没有准备好的。你可能会认为javascript的编写者会想到人们可能想替换字符串中的字符,并决定在语言中加入方便的方法。 评论 2015年3月26日4:43
  • 1
    @科林对OzrenTkalcecKrznaric做了不同的事情。OzrenTkalcecKrznaric假设字符串是静态的,并且可以在运行之前优化分割。这不一定是真的。如果每次运行时都必须进行拆分,那么子字符串方法在小字符串上的速度大约是原来的两倍到四倍,而且字符串越大,速度越快。在我看来,这使得子字符串对于大多数用例来说都是更好的实现,禁止对大型静态字符串进行大量更改。
    – 无线R3D
    评论 2016年3月2日15:33
  • 4
    问题是,在test2中,split和join不在for循环中,您可以将单个字符替换与多个字符替换进行比较(不公平),第一种方法对于单个替换更快,而第二种方法对于一个接一个的链式替换更好 评论 2016年7月22日11:40
35

编辑:一个优雅的解决方案是使用数组,尽管只建议用于小字符串:

String.prototype.replaceAt=函数(索引,字符){var a=this.split(“”);a[索引]=字符;返回a.join(“”);}

运行此代码段:

String.prototype.replaceAt=函数(索引,字符){var a=this.split(“”);a[索引]=字符;返回a.join(“”);}var str=“hello world”;str=str.replaceAt(3,“#”);document.write(str);

5
  • 11
    这对大字符串来说是不好的,如果您只需要使用substr来剪切,就不需要创建包含大量单元格的数组。。。 评论 2011年10月24日8:30
  • 1
    如果你需要改变很多字符,这很有用,而且很简单。 评论 2012年8月22日2:02
  • 7
    我在jsperf上创建了一个测试:jsperf.com/replace-character-by-index--Substr速度更快,从32字节到100kb都是一致的。我对此投了赞成票,尽管这让我很难过,但对于任何大小的字符串来说,substr都是更好的选择。 评论 2013年5月9日3:37
  • 这很不理想。 评论 2014年8月25日7:09
  • 如果您知道要使用小字符串,这是一个很好的快速解决方案。如果你可以扩展原型,那么你可以在两行中实现类似的行为:Array.prototype.replace=函数(index,val){this[index]=val;返回this;}; 'word'.split('').replace(1,'0').join('');//返回“w0rd” 评论 2018年3月20日15:04
34

在Javascript中,字符串是不可变的,因此您必须执行以下操作

var x=“你好,世界”x=x.substring(0,i)+‘h’+x.substring(i+1);

将x中i处的字符替换为“h”

21

函数dothis(){var x=document.getElementById(“x”).value;var index=document.getElementById(“index”).value;var text=document.getElementById(“text”).value;var length=document.getElementById(“length”).value;var arr=x.split(“”);arr.splice(索引、长度、文本);var结果=arr.join(“”);document.getElementById('output').innerHTML=result;console.log(结果);}dothis();
<input id=“x”type=“text”value=“White Dog”placeholder=“Enter text”/><input id=“index”type=“number”min=“0”value=“6”style=“width:50px”placeholder=“index“/><input id=“length”type=“number”min=“0”value=“1”style=“width:50px”placeholder=“longth”/><input id=“text”type=“text)value=“F”placeholder=“New character”/><br>运行<p id=“output”></p>

此方法适用于长度较小的字符串,但对于较大的文本可能速度较慢。

var x=“白狗”;var arr=x.split(“”);//[“W”、“h”、“i”、“t”、“e”、“”、“D”、“o”、“g”]重复排列(6,1,'F');/* 这里6是起始索引,1是要删除的数组元素数最后一个参数“F”是要插入的新字符。*/var结果=arr.join(“”);//“白雾”
5
  • 1
    我投了赞成票,因为我发现额外的描述很有用,而且实现简单而强大。谢谢!:-D类 评论 2020年6月24日21:55
  • 1
    阵列起始位置对于字符串到数组的转换也可能是一个好主意
    – 瓦伦
    评论 2020年7月25日9:51
  • 是的阵列起始位置也可以在这里使用。但Array.from是在ES2015中添加的,在较旧的浏览器中不受支持。另外,我个人更喜欢分裂函数,因为它提供了更多的自由来玩字符串模式。 评论 2020年7月26日17:42
  • 1
    如果只想替换1个字符,可以使用arr[6]=“F”;而不是.拼接(). 评论 2021年2月13日19:14
  • 您的建议已经由@fabio-phms在以上答案.我只是从另一个角度来看,我们可以灵活地替换一个或多个字符。 评论 2021年2月14日21:00
19

使用带回调的String.replace的单行程序(不支持表情符号):

//0-要替换的索引,“f”-替换字符串“dog”。替换(/./g,(c,i)=>i==0?”f’:c)//“雾”

解释:

//String.replace将在每个模式匹配时调用回调//在本例中-每个字符'dog'.replace(/./g,函数(字符,索引){如果(index==0)//我们想替换第一个字符返回'f'返回字符//其他字符保持不变})
1
  • 1
    非常简单&这是一个很棒的选项,不会强制扩展原型或创建新功能。谢谢您! 评论 2021年5月11日17:13
12

概括Afanasii Kurakin的答案,我们有:

函数replaceAt(str,index,ch){return str.replace(/./g,(c,i)=>i==索引?ch:c);}let str='Hello World';str=replaceAt(str,1,'u');console.log(str);//赫尔洛世界

让我们展开并解释正则表达式和replacer函数:

函数replaceAt(str,index,newChar){函数替换器(origChar,strIndex){if(strIndex===索引)return newChar;其他的return origChar;}return str.replace(/./g,替换器);}let str='Hello World';str=replaceAt(str,1,'u');console.log(str);//赫尔洛世界

正则表达式.只匹配一个字符。这个使其匹配for循环中的每个字符。这个替代品在给定原始字符和字符串中该字符所在位置的索引的情况下调用函数如果语句来确定是否返回origChar(原始字符)newChar(新字符).

6

var str=“hello world”;console.log(str);var arr=[…str];arr[0]=“H”;str=arr.join(“”);console.log(str);

2
5

其工作原理类似于阵列拼接:

String.prototype.splice=函数(i,j,str){返回this.substr(0,i)+str+this.subs(j,this.length);};
5

你可以试试

var strArr=str.split(“”);strArr[0]=“h”;str=strArr.join(“”);
2
  • 1
    这里没有太多解释。你能解释一下它是怎么工作的吗?“0”应该是我要更改的索引吗? 评论 2020年6月24日21:53
  • 1
    @SethEden是的,“0”应该是您想要更改的索引。 评论 2020年7月13日13:22
5

这很容易通过RegExp实现!

const str='你好RegEx!';常数指数=11;const replaceWith='p';//“你好,RegEx!”。替换(/^(.{11})(.)/,`$1p`);str.replace(新RegExp(`^(.{${index}})(.)`),`$1${replaceWith}`);//<“你好RegExp”
2
  • 1
    就当代JavaScript而言,到2022年,这是迄今为止最好的答案。 评论 2022年6月30日4:24
  • 2
    对于记录,可以使用lookbacking来避免捕获组。尚未检查此方法的性能影响(这可能是一个大问题),但它导致了整体简化:str.replace(新RegExp(`(?<=^.{${index}}).`),替换为) 评论 2022年12月10日4:09
5

使用扩展语法,您可以将字符串转换为数组,在给定位置分配字符,然后转换回字符串:

const str=“hello world”;函数replaceAt(s,i,c){const arr=[…s];//将字符串转换为数组arr[i]=c;//在位置i处设置字符c返回arr.join(“”);//返回字符串}//打印“哈罗世界”console.log(replaceAt(str,1,'a'));

1
  • 我会小心地把它放入这样的函数中。因为不可避免地会有人在循环中运行函数。在这种情况下,与他们需要时只需自己编写“convert to array”和“join”相比,这将是非常不理想的。然后他们自然会将其放在循环之外。
    – 马格纳
    评论 2022年4月29日7:59
5

你可以试试

var strArr=str.split(“”);strArr[0]=“h”;str=strArr.join(“”);

查看此功能以了解打印步骤

步骤(3)//       '#  '//       '## '//       '###'函数步骤(n,i=0,arr=Array(n).fill('').join('')){如果(i===n){回报;}str=arr.split('');str[i]=“#”;str=str.join(“”);console.log(str);步骤(n,(i=i+1),str);}
4

@CemKalyoncu:谢谢你的回答!

我还稍微修改了一下,使其更像Array.splice方法(并考虑了@Ates的注释):

spliceString=函数(字符串,索引,numToDelete,char){return string.subtr(0,index)+char+string.sUBR(index+numToDelete);}var myString=“hello world!”;拼接字符串(myString,myString.lastIndexOf('l'),2,'mlo');//“你好,虫洞!”
1
  • 不知道为什么这个被否决了。这是一个合法的答案。其工作原理如图所示。这与阵列拼接类型功能。
    – 吝啬
    评论 2015年5月18日14:40

如果要替换字符串中的字符,应该创建可变字符串。这些基本上是字符数组。您可以创建工厂:

函数MutableString(str){var结果=str.split(“”);result.toString=函数(){return this.join(“”);}返回结果;}

然后,您可以访问这些字符,当用作字符串时,整个数组将转换为字符串:

var x=可变字符串(“Hello”);x[0]=“B”;//是的,我们可以改变角色x.push(“!”);//性能良好:没有创建新字符串var y=“你好”,+x;//转换为字符串:“嗨,贝洛!”

您可以扩展字符串类型以包括inset方法:

String.prototype.append=函数(索引、值){返回this.slice(0,index)+值+this.slie(index);};var s=“新字符串”;警报(s.append(4,“完成”);

然后可以调用函数:

2

您可以使用子字符串函数进行连接,首先选择目标索引之前和目标索引之后的文本,然后与潜在的字符或字符串进行连接

const myString=“Hello world”;常数指数=3;const stringBeforeIndex=myString.substring(0,index);const stringAfterIndex=myString.substring(索引+1);const replaceChar=“X”;myString=字符串BeforeIndex+replaceChar+字符串AfterIndex;console.log(“新字符串-”,myString)

const myString=“Hello world”;设指数=3;myString=myString.substring(0,index)+“X”+myString.substring;
2

我的负指数安全方法:

/***@param{string}字符串*@param{number}索引*@param{string}替换*@返回{string}*/函数replaceAt(str,index,replacement){如果(index<0)index=str.length+index;if(索引<0||索引>=str.length)抛出新错误(`Index(${Index})out-of-bounds“${str}”`);返回str.substring(0,index)+替换+str.substrang(index+1);}

按如下方式使用:

replaceAt('my string',-1,'G')//'我的字符串'replaceAt('my-string',2,'yy')//'myyystring'replaceAt('my string',22,'yy')//未捕获错误:索引(22)超出边界“my string”
1

我做了一个函数,它的功能与您的要求类似,它检查字符串中的字符是否位于不允许的字符数组中,如果是,它将其替换为“”

var验证=函数(值){var notAllowed=[“;”,“_”,“>”,“<”,“'”,“%”,“$”,“&”,“/”,“|”,“:”,“=”,“*”];对于(var i=0;i<值长度;i++){if(notAllowed.indexOf(value.charAt(i))>-1){value=value.replace(value.charAt(i),“”);值=验证(值);}}返回值;}
1

如果您想在react/javascript中为单词或单个字符的索引设置样式,我会提供一个版本。

replaceAt(yourArrayOfIndexes、yourString/或ArrayofStrings)

工作示例:https://codesandbox.io/s/ov7zxp9mjq网址

函数replaceAt(indexArray,[…string]){const replaceValue=i=>string[i]=<b>{string[i]}</b>;indexArray.forEach(replaceValue);返回字符串;}

这是另一种替代方法

函数replaceAt(indexArray,[…string]){const startTag=“<b>”;const endTag=“</b>”;const-tagLetter=i=>string.splice(i,1,startTag+string[i]+endTag);indexArray.forEach(标记字母);return string.join('');}

还有一个。。。

函数replaceAt(indexArray,[…string]){for(设i=0;i<indexArray.length;i++){string=Object.assign(字符串{[indexArray[i]]:<b>{string[indexArray[i]]}</b>});}返回字符串;}
1

这是我使用三元和映射操作符的解决方案。如果你问我,更易读、更易维护的结尾更容易理解。

它更多地涉及es6和最佳实践。

函数replaceAt(){const replaceAt=document.getElementById('replaceAtt').value;const str=“ThisIsTestStringToReplaceCharAtSomePosition”;const newStr=数组.from(str).map((character,charIndex)=>charIndex==(replaceAt-1)?“”:字符).join(“”);console.log(`新字符串:${newStr}`);}
<input type=“number”id=“replaceAt”min=“1”max=“44”oninput=“replace At()”/>

0
0

假设你想替换千分位索引(基于0的索引)“Z”. 你可以使用Regex公司这样做。

var-re=var-re=新RegExp(“(.){”+K+“})((.)})”)str.replace(re,“$1A$`”);
  • 知道为什么这个标签没有用处吗? 评论 2017年3月17日21:05
  • 1
    我还没有检查这个正则表达式是否有效,但可能它被否决了,因为创建新字符串可能比编译状态机(正则表达式)快得多,因为编译状态机非常昂贵。 评论 2017年4月8日15:29
  • 这个答案也有错误,它有一个语法错误,其中var re=var re它有一个语义错误,它使用时没有$`任何需要
    – 弗伦
    评论 2023年7月27日6:02
0

您可以使用以下函数替换字符字符串在字符串的特定位置。要替换以下所有匹配情况,请使用String.prototype.replaceAllMatches()功能。

String.prototype.replaceMatch=函数(matchkey,replaceStr,matchIndex){var retStr=此,repeatedIndex=0;for(var x=0;(matchkey!=null)&&(retStr.indexOf(matchkey)>-1);x++){if(重复索引==0&&x==0){repeatedIndex=retStr.indexOf(匹配键);}else{//matchIndex>0repatedIndex=retStr.indexOf(匹配键,repatedindex+1);}如果(x==matchIndex){retStr=retStr.substring(0,repeatedIndex)+replaceStr+retStr.substring(repeatedIndex+(matchkey.length));matchkey=null;//打破循环。}}return retStr;};

测试:

var str=“yash yas$dfdas.**”;console.log('Index Matched replace:',str.replaceMatch('as','*',2));console.log('Index Matched replace:',str.replaceMatch('y','~',1));

输出:

匹配的索引替换:yash yas$dfd***匹配的索引替换为:yash~ as$dfdas**
0
0

我这样做是为了使字符串大小写正确,也就是说,第一个字母是大写字母,其余所有字母都是小写字母:

函数toPropertCase(someString){return someString.charAt(0).toUpperCase().concat(someString.toLowerBase().substring(1,someStringe.length));};

首先要做的是确保所有字符串都是小写的-someString.toLowerCase()

然后将第一个字符转换为大写-someString.charAt(0).toUpperCase()

然后取剩余字符串的子字符串减去第一个字符-someString.toLowerCase().substring(1,someString.length))

然后,它将这两者连接起来并返回新字符串-someString.charAt(0).toUpperCase().concat(someString.toLowerCase(。substring(1,someStringe.length))

可以为替换字符索引和替换字符添加新参数,然后形成两个子字符串,替换索引字符,然后以大致相同的方式连接。

1
  • 为了实现“正确的大小写”,将整个字符串变为小写,然后将第一个字符大写会不会比较简单?那么您就不必处理子字符串了。 评论 2023年4月11日14:38
-1

这个解决方案对负索引不起作用,所以我添加了一个补丁。

String.prototype.replaceAt=函数(索引,字符){如果(index>-1)返回this.substr(0,index)+字符+this.subs(index+字符.length);否则返回this.substr(0,this.length+index)+字符+this.subs(index+character.length);}
-3
“hello world”.replace(/(.{3})./,“1小时”)//“helho世界”
0
-4

这里的方法很复杂。我会这样做:

var myString=“这是我的字符串”;myString=myString.replace(myString.charAt(此处显示数字),“在此处插入替换”);

这很简单。

2
  • 8
    实际上不是。事实上,它将替换第一次出现的字符。还是错的。 评论 2014年1月5日20:03
  • 太不正确了,变得很有趣哈哈 评论 2023年1月17日12:45

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.