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.

user113716
fonte
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);
Tim Down
fonte
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:

Base33
fonte
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 !


fonte
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"
Visão
fonte
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>!"
Jake Stoeffler
fonte
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'
Ryan Ore
fonte
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.

David Hedlund
fonte
9
my_string          = "hello world";
my_insert          = " dear";
my_insert_location = 5;

my_string = my_string.split('');  
my_string.splice( my_insert_location , 0, my_insert );
my_string = my_string.join('');

https://jsfiddle.net/gaby_de_wilde/wz69nw9k/

user40521
fonte
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"
Sebastian Scholl
fonte
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.

Kamal
fonte
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.

Quelklef
fonte
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.

Inoperável
fonte
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);
mudshark2005
fonte
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!"

Madmadi
fonte
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"]]
]

))

Maheer Ali
fonte
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)

Pierre
fonte
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(''))

Ben Aston
fonte