Inserir uma string em um índice específico


Respostas:


257

Você pode criar um protótipo splice()para String.

Polyfill

if (!String.prototype.splice) {
    /**
     * {JSDoc}
     *
     * The splice() method changes the content of a string by removing a range of
     * characters and/or adding new characters.
     *
     * @this {String}
     * @param {number} start Index at which to start changing the string.
     * @param {number} delCount An integer indicating the number of old chars to remove.
     * @param {string} newSubStr The String that is spliced in.
     * @return {string} A new string with the spliced substring.
     */
    String.prototype.splice = function(start, delCount, newSubStr) {
        return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
    };
}

Exemplo

String.prototype.splice = function(idx, rem, str) {
    return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};

var result = "foo baz".splice(4, 0, "bar ");

document.body.innerHTML = result; // "foo bar baz"


EDIT: Modificado para garantir que remseja um valor absoluto.


6
Sei que é de 2010, mas a slicesolução abaixo é melhor e mais simples. (A emenda é destrutiva, a fatia não, e é melhor evitar modificar "objetos que você não conhece"). Esta solução absolutamente não deve ser a primeira resposta visível, mesmo que tenha feito sentido na época.
Eirik Birkeland

6
@EirikBirkeland: Strings são imutáveis. O código acima não modifica nenhum objeto. De qualquer maneira, sua noção de não modificar "objetos que você não conhece " impediria os métodos de mutação Array. Você está dizendo que prefere fazer em my_array[my_array.length] = itemvez de my_array.push(item)?

4
Desculpe, eu quis dizer "objetos que você NÃO POSSUI". Você está certo spliceneste caso; de fato, as cordas são imutáveis. Por esse motivo, acho que spliceé uma má escolha de palavras-chave. Minha principal objeção é contra a extensão arbitrária de protótipos, a menos que sejam polyfills padrão.
Eirik Birkeland

1
É uma prática incrivelmente ruim modificar objetos internos. Como vimos com o SmooshGate , isso corre o risco de quebrar seu código à medida que novas funcionalidades são adicionadas ao idioma e, se sua modificação irresponsável de alguma forma entrar em uma biblioteca que vê uma aceitação significativa na Web, pode bloquear o uso de um nome de método simples e claro para nova funcionalidade.
Sean

401

A inserção em um índice específico (em vez de, digamos, no primeiro caractere de espaço) deve usar a segmentação / segmentação de sequência de caracteres:

var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);

4
@AlejandroSalamancaMazuelo: substringficaria bem aqui. Eu prefiro sliceem geral porque é mais flexível (índices negativos, por exemplo "foo baz".slice(1, -2)). Também é um pouco mais curto, pelo pouco que vale a pena.
Tim Tim

8
O ES6 oferece uma alternativa melhor? Poderia pelo menos interpolação de string uso, como`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay

1
Isso não utiliza o deleterecurso, conforme incluído acima; resposta superior ...
Mr. Polywhirl

11
@ Mr.Polywhirl: Não. A questão não menciona a necessidade de fazer isso.
Tim Baixo

133

Aqui está um método que escrevi que se comporta como todas as outras linguagens de programação:

String.prototype.insert = function(index, string) {
  if (index > 0)
  {
    return this.substring(0, index) + string + this.substring(index, this.length);
  }

  return string + this;
};

//Example of use:
var something = "How you?";
something = something.insert(3, " are");
console.log(something)

Referência:


1
Pode ser necessário adicionar chaves {}nos blocos if-else.
Mr-IDE

3
Não, não precisa. Mas o elseé redundante.
Bitterblue

72

Basta fazer a seguinte função:

function insert(str, index, value) {
    return str.substr(0, index) + value + str.substr(index);
}

e depois use-o assim:

alert(insert("foo baz", 4, "bar "));

Saída: foo bar baz

Ele se comporta exatamente, como o C # (Sharp) String.Insert (int startIndex, valor da string).

NOTA: Esta função de inserção insere o valor da string (terceiro parâmetro) antes do índice inteiro especificado (segundo parâmetro) na string str (primeiro parâmetro) e, em seguida, retorna a nova string sem alterar str !


16

ATUALIZAÇÃO 2016: Aqui está outra função de protótipo divertida (mas mais séria!) Baseada na RegExpabordagem de uma linha (com suporte de prefix undefinedou negativo index):

/**
 * Insert `what` to string at position `index`.
 */
String.prototype.insert = function(what, index) {
    return index > 0
        ? this.replace(new RegExp('.{' + index + '}'), '$&' + what)
        : what + this;
};

console.log( 'foo baz'.insert('bar ', 4) );  // "foo bar baz"
console.log( 'foo baz'.insert('bar ')    );  // "bar foo baz"

Solução anterior (de volta a 2012) apenas por diversão :

var index = 4,
    what  = 'bar ';

'foo baz'.replace(/./g, function(v, i) {
    return i === index - 1 ? v + what : v;
});  // "foo bar baz"

1
Isso também é ótimo se você precisar inserir texto em vários índices em uma string. Veja minha resposta abaixo, se for esse o caso.
Jake Stoeffler

12

Se alguém estiver procurando uma maneira de inserir texto em vários índices em uma string, tente o seguinte:

String.prototype.insertTextAtIndices = function(text) {
    return this.replace(/./g, function(character, index) {
        return text[index] ? text[index] + character : character;
    });
};

Por exemplo, você pode usar isso para inserir <span>tags em certas compensações em uma string:

var text = {
    6: "<span>",
    11: "</span>"
};

"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"

1
Eu tentei esse método, mas substitui '6' e '11' por variáveis ​​que não funcionam - o que estou fazendo de errado - ajuda por favor. Agradecemos antecipadamente :)
Dex Dave

1
6 e 11 são os índices nos quais o texto será inserido na string. 6: "<span>"diz: no índice 6, insira o texto "<span>". Você está dizendo que deseja usar o valor de uma variável inteira como índice de inserção? Se for esse o caso, tente algo comovar a=6, text = {}; text[a] = "<span>";
Jake Stoeffler

1
sim, eu quero usar variáveis ​​inteiras como inserção, seu método funcionou - obrigado - é isso que eu usei var a = 6; var b = 11; texto = {}; texto [a] = "xx"; texto [b] = "aa"; - existe uma maneira melhor de escrever isso?
Dex Dave

11

Isso é basicamente fazer o que @ Bass33 está fazendo, exceto que eu também estou dando a opção de usar um índice negativo para contar a partir do final. Como o método substr permite.

// use a negative index to insert relative to the end of the string.

String.prototype.insert = function (index, string) {
  var ind = index < 0 ? this.length + index  :  index;
  return  this.substring(0, ind) + string + this.substring(ind, this.length);
};

Caso de uso: digamos que você tenha imagens em tamanho real usando uma convenção de nomenclatura, mas não pode atualizar os dados para também fornecer URLs em miniatura.

var url = '/images/myimage.jpg';
var thumb = url.insert(-4, '_thm');

//    result:  '/images/myimage_thm.jpg'

9

Dado o seu exemplo atual, você pode obter o resultado quer

var txt2 = txt1.split(' ').join(' bar ')

ou

var txt2 = txt1.replace(' ', ' bar ');

mas, como você pode fazer essas suposições, você também pode pular diretamente para o exemplo de Gullen.

Em uma situação em que você realmente não pode fazer nenhuma suposição que não seja baseada no índice de caracteres, eu realmente procuraria uma solução de substring.



6

Eu sei que este é um tópico antigo, no entanto, aqui está uma abordagem realmente eficaz.

var tn = document.createTextNode("I am just  to help")
t.insertData(10, "trying");

O que é ótimo nisso é que ele coage o conteúdo do nó. Portanto, se esse nó já estivesse no DOM, você não precisaria usar nenhum seletor de consulta ou atualizar o innerText. As alterações refletiriam devido à sua ligação.

Se você precisar de uma sequência, basta acessar a propriedade de conteúdo de texto do nó.

tn.textContent
#=> "I am just trying to help"

6

Bem, podemos usar os métodos substring e slice.

String.prototype.customSplice = function (index, absIndex, string) {
    return this.slice(0, index) + string+ this.slice(index + Math.abs(absIndex));
};


String.prototype.replaceString = function (index, string) {
    if (index > 0)
        return this.substring(0, index) + string + this.substring(index, this.length);

    return string + this;
};


console.log('Hello Developers'.customSplice(6,0,'Stack ')) // Hello Stack Developers
console.log('Hello Developers'.replaceString(6,'Stack ')) //// Hello Stack Developers

O único problema de um método de substring é que ele não funcionará com um índice negativo. É sempre pegar o índice de string da 0ª posição.


O que absIndex suporta?
Enrique Bermúdez

Btw, obrigado pelo segundo método. Ele funciona como um encanto!
Enrique Bermúdez

5
function insertString(string, insertion, place) {
  return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}

Então, para você, seria insertString("foo baz", "bar", 3);

Obviamente, isso seria uma tinta para usar, porque você precisa fornecer sua string para a função todas as vezes, mas no momento não sei como torná-la algo mais fácil, como a string.replace(insertion, place). A idéia ainda permanece, no entanto.


4

Você pode usar expressões regulares com um padrão dinâmico .

var text = "something";
var output = "                    ";
var pattern = new RegExp("^\\s{"+text.length+"}");
var output.replace(pattern,text);

saídas:

"something      "

Isso substitui os text.lengthcaracteres de espaço em branco no início da string output. Os RegExpmeios ^\- início de uma linha, \squalquer caractere de espaço em branco, repetidas {n}vezes, neste caso text.length. Use \\para \escapar de barras invertidas ao criar esse tipo de padrão a partir de strings.


3

outra solução, corte a corda em 2 e coloque-a no meio.

var str = jQuery('#selector').text();

var strlength = str.length;

strf = str.substr(0 , strlength - 5);
strb = str.substr(strlength - 5 , 5);

jQuery('#selector').html(strf + 'inserted' + strb);

3

Você pode fazer isso facilmente com regexp em uma linha de código

const str = 'Hello RegExp!';
const index = 6;
const insert = 'Lovely ';
    
//'Hello RegExp!'.replace(/^(.{6})(.)/, `$1Lovely $2`);
const res = str.replace(new RegExp(`^(.{${index}})(.)`), `$1${insert}$2`);
    
console.log(res);

"Olá, adorável RegExp!"


2

Usando fatia

Você pode usar slice(0,index) + str + slice(index). Ou você pode criar um método para isso.

String.prototype.insertAt = function(index,str){
  return this.slice(0,index) + str + this.slice(index)
}
console.log("foo bar".insertAt(4,'baz ')) //foo baz bar

Método de emenda para Strings

Você pode split()a string principal e adicionar e usar o normalsplice()

String.prototype.splice = function(index,del,...newStrs){
  let str = this.split('');
  str.splice(index,del,newStrs.join('') || '');
  return str.join('');
}


 var txt1 = "foo baz"

//inserting single string.
console.log(txt1.splice(4,0,"bar ")); //foo bar baz


//inserting multiple strings
console.log(txt1.splice(4,0,"bar ","bar2 ")); //foo bar bar2 baz


//removing letters
console.log(txt1.splice(1,2)) //f baz


//remving and inseting atm
console.log(txt1.splice(1,2," bar")) //f bar baz

Aplicando splice () em vários índices

O método utiliza uma matriz de matrizes, cada elemento da matriz representando um único splice().

String.prototype.splice = function(index,del,...newStrs){
  let str = this.split('');
  str.splice(index,del,newStrs.join('') || '');
  return str.join('');
}


String.prototype.mulSplice = function(arr){
  str = this
  let dif = 0;
  
  arr.forEach(x => {
    x[2] === x[2] || [];
    x[1] === x[1] || 0;
    str = str.splice(x[0] + dif,x[1],...x[2]);
    dif += x[2].join('').length - x[1];
  })
  return str;
}

let txt = "foo bar baz"

//Replacing the 'foo' and 'bar' with 'something1' ,'another'
console.log(txt.splice(0,3,'something'))
console.log(txt.mulSplice(
[
[0,3,["something1"]],
[4,3,["another"]]
]

))


1

Eu queria comparar o método usando substring e o método usando slice da Base33 e user113716 respectivamente, para fazer isso, escrevi algum código

também dê uma olhada nessa comparação de desempenho, substring, fatia

O código que eu usei cria cadeias enormes e insere a "barra" da cadeia várias vezes na cadeia enorme

if (!String.prototype.splice) {
    /**
     * {JSDoc}
     *
     * The splice() method changes the content of a string by removing a range of
     * characters and/or adding new characters.
     *
     * @this {String}
     * @param {number} start Index at which to start changing the string.
     * @param {number} delCount An integer indicating the number of old chars to remove.
     * @param {string} newSubStr The String that is spliced in.
     * @return {string} A new string with the spliced substring.
     */
    String.prototype.splice = function (start, delCount, newSubStr) {
        return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
    };
}

String.prototype.splice = function (idx, rem, str) {
    return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};


String.prototype.insert = function (index, string) {
    if (index > 0)
        return this.substring(0, index) + string + this.substring(index, this.length);

    return string + this;
};


function createString(size) {
    var s = ""
    for (var i = 0; i < size; i++) {
        s += "Some String "
    }
    return s
}


function testSubStringPerformance(str, times) {
    for (var i = 0; i < times; i++)
        str.insert(4, "bar ")
}

function testSpliceStringPerformance(str, times) {
    for (var i = 0; i < times; i++)
        str.splice(4, 0, "bar ")
}


function doTests(repeatMax, sSizeMax) {
    n = 1000
    sSize = 1000
    for (var i = 1; i <= repeatMax; i++) {
        var repeatTimes = n * (10 * i)
        for (var j = 1; j <= sSizeMax; j++) {
            var actualStringSize = sSize *  (10 * j)
            var s1 = createString(actualStringSize)
            var s2 = createString(actualStringSize)
            var start = performance.now()
            testSubStringPerformance(s1, repeatTimes)
            var end = performance.now()
            var subStrPerf = end - start

            start = performance.now()
            testSpliceStringPerformance(s2, repeatTimes)
            end = performance.now()
            var splicePerf = end - start

            console.log(
                "string size           =", "Some String ".length * actualStringSize, "\n",
                "repeat count          = ", repeatTimes, "\n",
                "splice performance    = ", splicePerf, "\n",
                "substring performance = ", subStrPerf, "\n",
                "difference = ", splicePerf - subStrPerf  // + = splice is faster, - = subStr is faster
                )

        }
    }
}

doTests(1, 100)

A diferença geral de desempenho é marginal, na melhor das hipóteses, e ambos os métodos funcionam muito bem (mesmo em cadeias de comprimento ~~ 12000000)


0
  1. Instanciar uma matriz a partir da string
  2. Usar matriz # emenda
  3. Stringify novamente usando Array # join

Os benefícios dessa abordagem são duplos:

  1. Simples
  2. Compatível com ponto de código Unicode

const pair = Array.from('USDGBP')
pair.splice(3, 0, '/')
console.log(pair.join(''))

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.