Insertar una cadena en un índice específico

Respuestas:

257

Podrías crear tu propio prototipo splice()en 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));
    };
}

Ejemplo

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"


EDITAR: lo modificó para garantizar que remsea ​​un valor absoluto.

usuario113716
fuente
66
Sé que esto es de 2010, pero la slicesolución a continuación es mejor y más simple. (Splice es destructivo, slice no lo es, y es mejor evitar modificar "objetos que no conoces"). Esta solución no debería ser la primera respuesta visible, aunque haya tenido sentido en ese momento.
Eirik Birkeland
66
@EirikBirkeland: las cadenas son inmutables. El código anterior no modifica ningún objeto. De cualquier manera, su noción de no modificar "objetos que no conoce " impediría los métodos de mutación de matriz. ¿Dices que prefieres hacer en my_array[my_array.length] = itemlugar de my_array.push(item)?
44
Lo siento, quise decir "objetos que NO TIENES". Tienes razón spliceen este caso; de hecho las cuerdas son inmutables. Por esta razón, creo que splicees una mala elección de palabras clave. Mi principal objeción es en contra de extender prototipos arbitrariamente, a menos que sean polyfills estándar.
Eirik Birkeland
1
Es una práctica increíblemente mala modificar un objeto incorporado. Como vimos con SmooshGate , esto corre el riesgo de romper su código a medida que se agrega una nueva funcionalidad al lenguaje y, si su modificación irresponsable de alguna manera entra en una biblioteca que ve una absorción significativa en la web, podría bloquear el uso de un nombre de método simple y claro para nueva funcionalidad.
Sean
401

Insertar en un índice específico (en lugar de, digamos, en el primer carácter de espacio) tiene que usar la división / subcadena de cadenas:

var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);
Tim Down
fuente
44
@AlejandroSalamancaMazuelo: substringestaría bien aquí. Prefiero sliceen general porque es más flexible (índices negativos, por ejemplo "foo baz".slice(1, -2)). También es un poco más corto, por lo poco que vale.
Tim Down
8
¿ES6 ofrece una mejor alternativa? Al menos podría usar interpolación de cadenas, como`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay
1
Esto no utiliza la deletefunción incluida en lo anterior; respuesta principal ...
Sr. Polywhirl
11
@ Mr.Polywhirl: No. La pregunta no menciona la necesidad de hacer eso.
Tim Down
133

Aquí hay un método que escribí que se comporta como todos los demás lenguajes de programación:

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)

Referencia:

Base33
fuente
1
Es posible que deba agregar llaves {}a los bloques if-else.
Mr-IDE
3
No, no es necesario. Pero el elsees redundante.
Bitterblue
72

Simplemente realice la siguiente función:

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

y luego úsalo así:

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

Salida: foo bar baz

Se comporta exactamente, como C # (Sharp) String.Insert (int startIndex, valor de cadena).

NOTA: Esta función de inserción inserta el valor de la cadena (tercer parámetro) antes del índice entero especificado (segundo parámetro) en la cadena str (primer parámetro), ¡y luego devuelve la nueva cadena sin cambiar str !


fuente
16

ACTUALIZACIÓN 2016: Aquí hay otra función prototipo solo por diversión (¡pero más seria!) Basada en el RegExpenfoque de una línea (con soporte previo undefinedo 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"

Solución anterior (de vuelta a 2012) solo por diversión :

var index = 4,
    what  = 'bar ';

'foo baz'.replace(/./g, function(v, i) {
    return i === index - 1 ? v + what : v;
});  // "foo bar baz"
Visión
fuente
1
Esto también es excelente si necesita insertar texto en múltiples índices en una cadena. Vea mi respuesta a continuación si ese es el caso.
Jake Stoeffler
12

Si alguien está buscando una forma de insertar texto en múltiples índices en una cadena, pruebe esto:

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

Por ejemplo, puede usar esto para insertar <span>etiquetas en ciertos desplazamientos en una cadena:

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

"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"
Jake Stoeffler
fuente
1
Intenté este método pero reemplacé '6' y '11' con variables que no funcionan, ¿qué estoy haciendo mal? Ayuda por favor. Gracias de antemano :)
Dex Dave
1
6 y 11 son los índices en los que el texto se insertará en la cadena. 6: "<span>"dice: en el índice 6, inserte el texto "<span>". ¿Está diciendo que desea utilizar el valor de una variable entera como índice de inserción? Si ese es el caso, intente algo comovar a=6, text = {}; text[a] = "<span>";
Jake Stoeffler
1
sí, quiero usar variables enteras como inserción, su método funcionó, gracias, esto es lo que usé var a = 6; var b = 11; texto = {}; texto [a] = "xx"; texto [b] = "aa"; - ¿Hay una mejor manera de escribir eso?
Dex Dave
11

Básicamente, esto es lo que está haciendo @ Bass33, excepto que también estoy dando la opción de usar un índice negativo para contar desde el final. Algo así como lo permite el método substr.

// 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: supongamos que tiene imágenes de tamaño completo mediante una convención de nomenclatura pero no puede actualizar los datos para proporcionar también URL en miniatura.

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

//    result:  '/images/myimage_thm.jpg'
Ryan Ore
fuente
9

Dado su ejemplo actual, podría lograr el resultado ya sea

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

o

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

pero dado que puede hacer tales suposiciones, es mejor pasar directamente al ejemplo de Gullen.

En una situación en la que realmente no puede hacer ninguna suposición que no sea basada en el índice de caracteres, entonces realmente elegiría una solución de subcadena.

David Hedlund
fuente
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/

usuario40521
fuente
6

Sé que este es un hilo viejo, sin embargo, aquí hay un enfoque realmente efectivo.

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

Lo bueno de esto es que coacciona el contenido del nodo. Entonces, si este nodo ya estuviera en el DOM, no necesitaría usar ningún selector de consulta o actualizar el texto interno. Los cambios se reflejarían debido a su vinculación.

Si necesita una cadena, simplemente acceda a la propiedad de contenido de texto del nodo.

tn.textContent
#=> "I am just trying to help"
Sebastian Scholl
fuente
6

Bueno, podemos usar tanto el método de subcadena como el de corte.

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

El único problema de un método de subcadena es que no funcionará con un índice negativo. Siempre toma el índice de cadena desde la posición 0.

kamal
fuente
¿Para qué sirve absIndex?
Enrique Bermúdez
Por cierto, gracias por el segundo método. ¡Funciona a las mil maravillas!
Enrique Bermúdez
5
function insertString(string, insertion, place) {
  return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}

Entonces, para ti, sería insertString("foo baz", "bar", 3);

Obviamente, esta sería una pintura para usar porque tienes que proporcionar tu cadena a la función cada vez, pero por el momento no sé cómo convertirla en algo más fácil como a string.replace(insertion, place). Sin embargo, la idea sigue en pie.

Quelklef
fuente
4

Puede usar expresiones regulares con un patrón dinámico .

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

salidas:

"something      "

Esto reemplaza los text.lengthcaracteres de espacios en blanco al comienzo de la cadena output. Los RegExpmedios ^\: comienzo de una línea, \scualquier carácter de espacio en blanco, {n}veces repetidas , en este caso text.length. Úselo \\para \escapar de las barras invertidas cuando construya este tipo de patrones a partir de cadenas.

Inoperable
fuente
3

otra solución, corta la cuerda en 2 y pon una cuerda en el medio.

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
fuente
3

Puedes hacerlo fácilmente con regexp en una línea 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);

"¡Hola, encantadora RegExp!"

Madmadi
fuente
2

Usando rebanada

Puedes usar slice(0,index) + str + slice(index). O puedes crear un método para ello.

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 empalme para cadenas

Puede split()la cadena principal y agregar y luego usar 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 () en múltiples índices

El método toma una matriz de matrices, cada elemento de la matriz representa un ú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
fuente
1

Quería comparar el método usando la subcadena y el método usando el segmento de Base33 y user113716 respectivamente, para hacer eso escribí un código

También eche un vistazo a esta comparación de rendimiento, subcadena, corte

El código que utilicé crea cadenas enormes e inserta la "barra" de cadenas varias veces en la cadena 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)

La diferencia general en el rendimiento es marginal en el mejor de los casos y ambos métodos funcionan bien (incluso en cadenas de longitud ~~ 12000000)

Pierre
fuente
0
  1. Instanciar una matriz de la cadena
  2. Usar matriz # empalme
  3. Stringify nuevamente usando Array # join

Los beneficios de este enfoque son dobles:

  1. Sencillo
  2. Punto de código Unicode compatible

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

Ben Aston
fuente