如何在JavaScript中替换特定索引处的字符?

San*_*osh 501 javascript string replace character-replacement

我有一个字符串,让我们说Hello world,我需要在索引3处替换char.如何通过指定索引来替换char?

var str = "hello world";
Run Code Online (Sandbox Code Playgroud)

我需要类似的东西

str.replaceAt(0,"h");
Run Code Online (Sandbox Code Playgroud)

Cem*_*ncu 566

在JavaScript中,字符串是不可变的,这意味着您可以做的最好的事情是创建一个包含更改内容的新字符串,并指定变量指向它.

您需要自己定义该replaceAt()功能:

String.prototype.replaceAt=function(index, replacement) {
    return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

var hello="Hello World";
alert(hello.replaceAt(2, "!!")); //should display He!!o World
Run Code Online (Sandbox Code Playgroud)

  • 请注意,扩展基本JavaScript类通常不是一个好主意.请改用普通的实用功能. (90认同)
  • 我必须问为什么?原型支持就是为了这个目的. (83认同)
  • 我不同意,即使你检测到该功能是否存在,后来的库仍然可以使用/创建一个类似的功能 - 2个糟糕的想法使得更糟糕的一个.一般来说,只是永远不要玩其他人的代码(包括核心系统).创建一个新功能. (77认同)
  • @CemKalyoncu:它*可以*使代码在其他库中运行不好.但我自己也没有被这种方式所困扰. (28认同)
  • @alex:你是对的,你真的需要在做之前检查一下这个函数是否存在.但即使它确实如此,它应该完全相同的操作. (6认同)
  • 如果你关心微优化,`substring`往往比`substr`或`slice`更快. (5认同)
  • 值得注意的是,如果将一个数字作为字符参数传递,它将插入索引而不是用它替换索引处的字符. (2认同)
  • @CemKalyoncu在本对象实例上使用`for in`语句时,将任何方法添加到本机对象甚至原型都会使其"可列表".这就是我同意@AtesGoral的原因 (2认同)
  • 这种说法在2015年继续 - 延长或不延长.但是我要指出,无论哪种方式都存在命名冲突的可能性.这只是一个问题,在原型级别或全局窗口范围内您更喜欢它. (2认同)
  • 请不要编辑答案以反映您的意见。John 建议使用不同的命名系统以避免名称冲突。但我支持我的决定。如果您需要这样做,您可能没有使用任何其他具有类似功能的库。即使它存在,也不会发生任何变化,因为该函数会按照它所说的去做。如果您使用相同和不同的功能实现此功能,则不应称自己为程序员并分发您的库。 (2认同)

rah*_*hul 85

replaceAtJavaScript中没有任何功能.您可以使用以下代码替换指定位置的任何字符串中的任何字符:

function rep() {
    var str = 'Hello World';
    str = setCharAt(str,4,'a');
    alert(str);
}

function setCharAt(str,index,chr) {
    if(index > str.length-1) return str;
    return str.substr(0,index) + chr + str.substr(index+1);
}
Run Code Online (Sandbox Code Playgroud)
<button onclick="rep();">click</button>
Run Code Online (Sandbox Code Playgroud)

  • 注意事项:[substr被认为是旧函数,应尽可能避免使用](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr )。 (2认同)

Guf*_*ffa 62

你不能.取位置前后的字符并连接成一个新字符串:

var s = "Hello world";
var index = 3;
s = s.substr(0, index) + 'x' + s.substr(index + 1);
Run Code Online (Sandbox Code Playgroud)

  • @Ates:替换函数不进行就地替换,它创建一个新字符串并返回它. (12认同)
  • [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substr) 建议使用 `String.prototype.substring` 而不是 `String.prototype.substr` . (3认同)

Ozr*_*ric 31

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

  • 方法1:使用两个子串分割字符串并填充它们之间的字符
  • METHOD2:将字符串转换为字符数组,替换一个数组成员并加入它

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

@FabioPhms:你的方法是我最初使用的方法,我担心它对很多字符的字符串都很糟糕.然而,问题是很多角色是什么?我在10"lorem ipsum"段落上进行了测试,花了几毫秒.然后我用10倍大的字符串测试它 - 真的没什么大不同.嗯.

@vsync,@ Cory Mawhorter:你的评论是明确的; 然而,再一次,什么是大字符串?我同意,对于32 ... 100kb性能应该更好,并且应该使用substring-variant进行这一个字符替换操作.

但是,如果我必须进行一些替换,会发生什么?

我需要执行自己的测试来证明在这种情况下更快.假设我们有一个算法可以操作一个由1000个字符组成的相对较短的字符串.我们希望平均每个字符串中的每个字符都会被替换100次.所以,测试这样的代码的代码是:

var str = "... {A LARGE STRING HERE} ...";

for(var i=0; i<100000; i++)
{
  var n = '' + Math.floor(Math.random() * 10);
  var p = Math.floor(Math.random() * 1000);
  // replace character *n* on position *p*
}
Run Code Online (Sandbox Code Playgroud)

我为此创造了一个小提琴,它就在这里.有两个测试,TEST1(子串)和TEST2(阵列转换).

结果:

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

似乎数组转换比子串要好2个数量级!那么 - 到底发生了什么?

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

所以,这就是为工作选择合适的工具.再次.

  • 将您的测试移至jsperf,结果大不相同:http://jsperf.com/string-replace-character.这就是为工作选择合适的工具;) (5认同)
  • 问题是在test2上,split和join在for循环之外,你将单个char替换与多个替换(不公平),第一个方法对于单个替换更快,第二个方法对于一个接一个的链式替换更好 (3认同)

Fab*_*hms 28

使用矢量通常最有效地联系String.

我建议以下功能:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}
Run Code Online (Sandbox Code Playgroud)

运行此代码段:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}

var str = "hello world";
str = str.replaceAt(3, "#");

document.write(str);
Run Code Online (Sandbox Code Playgroud)

  • 这对于大字符串是不好的,如果你可以只使用substr来剪切它,就不需要创建一个具有疯狂数量的单元格的数组... (9认同)
  • 我在jsperf上创建了一个测试:http://jsperf.com/replace-character-by-index - Substr更快,从32bytes到100kb一致.我赞成这一点,尽管这让我感到很伤心,即使这感觉更好,但对于任何大小的字符串来说,substr都是更好的选择. (6认同)

Dev*_*Dev 26

在Javascript字符串是不可变的,所以你必须做类似的事情

var x = "Hello world"
x = x.substring(0, i) + 'h' + x.substring(i+1);
Run Code Online (Sandbox Code Playgroud)

用'h'替换i中x的字符


col*_*lin 26

str = str.split('');
str[3] = 'h';
str = str.join('');
Run Code Online (Sandbox Code Playgroud)

  • 清晰简单,但在使用`split`和`join`时,目前不能使用表情符号(例如) (3认同)
  • 对于 es6,我认为 Array.from(str) 现在可能是更好的选择,但我带着这些知识来到这里并从你那里学到了一些同样简洁的东西,所以谢谢你! (2认同)

Ste*_*uan 8

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

function replaceAt(str, index, ch) {
    return str.replace(/./g, (c, i) => i == index ? ch : c);
}

let str = 'Hello World';
str = replaceAt(str, 1, 'u');
console.log(str); // Hullo World
Run Code Online (Sandbox Code Playgroud)

让我们扩展和解释正则表达式和替换函数:

function replaceAt(str, index, newChar) {
    function replacer(origChar, strIndex) {
        if (strIndex === index)
            return newChar;
        else
            return origChar;
    }
    return str.replace(/./g, replacer);
}

let str = 'Hello World';
str = replaceAt(str, 1, 'u');
console.log(str); // Hullo World
Run Code Online (Sandbox Code Playgroud)

正则表达式.正好匹配一个字符。这g使它匹配 for 循环中的每个字符。在replacer给定原始字符和该字符在字符串中的位置的索引的情况下调用该函数。我们做了一个简单的if声明来确定我们是否要返回origCharnewChar


Afa*_*kin 6

一线使用String.replace和回调(不支持表情符号):

// 0 - index to replace, 'f' - replacement string
'dog'.replace(/./g, (c, i) => i == 0? 'f': c)
// "fog"
Run Code Online (Sandbox Code Playgroud)

解释:

//String.replace will call the callback on each pattern match
//in this case - each character
'dog'.replace(/./g, function (character, index) {
   if (index == 0) //we want to replace the first character
     return 'f'
   return character //leaving other characters the same
})
Run Code Online (Sandbox Code Playgroud)


Avi*_*hen 6

var str = "hello world";
console.log(str);
var arr = [...str];
arr[0] = "H";
str = arr.join("");
console.log(str);
Run Code Online (Sandbox Code Playgroud)


Ara*_*yan 5

其工作原理类似于Array.splice

String.prototype.splice = function (i, j, str) {
    return this.substr(0, i) + str + this.substr(j, this.length);
};
Run Code Online (Sandbox Code Playgroud)


Vik*_*tya 5

function dothis() {
  var x = document.getElementById("x").value;
  var index = document.getElementById("index").value;
  var text = document.getElementById("text").value;
  var arr = x.split("");
  arr.splice(index, 1, text);
  var result = arr.join("");
  document.getElementById('output').innerHTML = result;
  console.log(result);
}
dothis();
Run Code Online (Sandbox Code Playgroud)
<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="text" type="text" value="F" placeholder="New character" />
<br>
<button id="submit" onclick="dothis()">Run</button>
<p id="output"></p>
Run Code Online (Sandbox Code Playgroud)

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

var x = "White Dog";
var arr = x.split(""); // ["W", "h", "i", "t", "e", " ", "D", "o", "g"]
arr.splice(6, 1, 'F');
var result = arr.join(""); // "White Fog"

/* 
  Here 6 is starting index and 1 is no. of array elements to remove and 
  final argument 'F' is the new character to be inserted. 
*/
Run Code Online (Sandbox Code Playgroud)


Meh*_*mar 5

你可以试试

var strArr = str.split("");

strArr[0] = 'h';

str = strArr.join("");
Run Code Online (Sandbox Code Playgroud)


Mad*_*adi 5

使用正则表达式可以轻松实现这一点!

const str = 'Hello RegEx!';
const index = 11;
const replaceWith = 'p';

//'Hello RegEx!'.replace(/^(.{11})(.)/, `$1p`);
str.replace(new RegExp(`^(.{${ index }})(.)`), `$1${ replaceWith }`);

//< "Hello RegExp"
Run Code Online (Sandbox Code Playgroud)

  • 作为记录,lookbehind 可用于避免捕获组。尚未检查此方法的性能影响(这可能是一个大问题),但它会导致整体简化: `str.replace(new RegExp(\`(?&lt;=^.{${index}}).\ `), 替换为)` (2认同)

Rid*_*ola 5

你可以尝试

var strArr = str.split("");

strArr[0] = 'h';

str = strArr.join("");
Run Code Online (Sandbox Code Playgroud)

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

steps(3)
//       '#  '
//       '## '
//       '###'

function steps(n, i = 0, arr = Array(n).fill(' ').join('')) {
  if (i === n) {
    return;
  }

  str = arr.split('');
  str[i] = '#';
  str = str.join('');
  console.log(str);

  steps(n, (i = i + 1), str);
}

Run Code Online (Sandbox Code Playgroud)


Gyu*_*Fox 5

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

const str = "hello world";

function replaceAt(s, i, c) {
  const arr = [...s];  // Convert string to array
  arr[i] = c;          // Set char c at pos i
  return arr.join(''); // Back to string
}

// prints "hallo world"
console.log(replaceAt(str, 1, 'a'));
Run Code Online (Sandbox Code Playgroud)