Insérer une chaîne à un index spécifique

Réponses:

257

Vous pouvez créer votre propre prototype splice()dans 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));
    };
}

Exemple

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: l'a modifié pour garantir qu'il rems'agit d'une valeur absolue.

user113716
la source
6
Je sais que cela date de 2010, mais la slicesolution ci-dessous est meilleure et plus simple. (Splice est destructif, slice ne l'est pas, et il vaut mieux éviter de modifier "des objets que vous ne connaissez pas"). Cette solution ne devrait absolument pas être la première réponse visible, même si elle avait du sens à l'époque.
Eirik Birkeland
6
@EirikBirkeland: Les chaînes sont immuables. Le code ci-dessus ne modifie aucun objet. Quoi qu'il en soit, votre idée de ne pas modifier les «objets que vous ne connaissez pas » empêcherait les méthodes de mutation de tableau. Vous dites que vous préférez faire à la my_array[my_array.length] = itemplace de my_array.push(item)?
4
Désolé, je voulais dire "des objets que vous ne possédez pas". Vous avez raison splicedans ce cas; en effet, les cordes sont immuables. Pour cette raison, je pense que splicec'est un mauvais choix de mots clés. Ma principale objection est contre l'extension arbitraire des prototypes, à moins qu'il ne s'agisse de polyfills standard.
Eirik Birkeland
1
Il est incroyablement mauvais de modifier un objet intégré. Comme nous l'avons vu avec SmooshGate , cela risque de casser votre code à mesure que de nouvelles fonctionnalités sont ajoutées au langage et, si votre modification irresponsable pénètre d'une manière ou d'une autre dans une bibliothèque qui voit une adoption significative sur le Web, elle pourrait bloquer l'utilisation d'un nom de méthode simple et clair pour de nouvelles fonctionnalités.
Sean
401

L'insertion à un index spécifique (plutôt que, disons, au premier caractère d'espace) doit utiliser le découpage / sous-chaîne de chaînes:

var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);
Tim Down
la source
4
@AlejandroSalamancaMazuelo: ce substringserait bien ici. Je préfère sliceen général car c'est plus flexible (indices négatifs, par exemple "foo baz".slice(1, -2)). Il est également légèrement plus court, pour le peu qui en vaut la peine.
Tim Down
8
ES6 offre-t-il une meilleure alternative? Pourrait au moins utiliser l'interpolation de chaînes, comme`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay
1
Cela n'utilise pas la deletefonctionnalité incluse dans ce qui précède; meilleure réponse ...
M. Polywhirl
11
@ Mr.Polywhirl: Non. La question ne mentionne pas la nécessité de le faire.
Tim Down
133

Voici une méthode que j'ai écrite qui se comporte comme tous les autres langages de programmation:

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)

Référence:

Base33
la source
1
Vous devrez peut-être ajouter des accolades {}aux blocs if-else.
Mr-IDE
3
Non, pas besoin. Mais elsec'est redondant.
Bitterblue
72

Faites simplement la fonction suivante:

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

puis l'utiliser comme ça:

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

Sortie: foo bar baz

Il se comporte exactement comme le String.Insert C # (Sharp) (int startIndex, string value).

REMARQUE: cette fonction d'insertion insère la valeur de chaîne (troisième paramètre) avant l' index d' entier spécifié (deuxième paramètre) dans la chaîne str (premier paramètre), puis renvoie la nouvelle chaîne sans modifier str !


la source
16

MISE À JOUR 2016: Voici une autre fonction prototype juste pour le plaisir (mais plus sérieuse!) Basée sur une RegExpapproche à une ligne (avec support de pré-ajout activé undefinedou négatif 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"

Précédente solution ( juste pour 2012) :

var index = 4,
    what  = 'bar ';

'foo baz'.replace(/./g, function(v, i) {
    return i === index - 1 ? v + what : v;
});  // "foo bar baz"
Vision
la source
1
C'est également très bien si vous devez insérer du texte à plusieurs index dans une chaîne. Voir ma réponse ci-dessous si c'est le cas.
Jake Stoeffler
12

Si quelqu'un cherche un moyen d'insérer du texte à plusieurs index dans une chaîne, essayez ceci:

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

Par exemple, vous pouvez utiliser ceci pour insérer des <span>balises à certains décalages dans une chaîne:

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

"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"
Jake Stoeffler
la source
1
J'ai essayé cette méthode mais j'ai remplacé «6» et «11» par des variables qui ne fonctionnent pas - qu'est-ce que je fais mal - aidez s'il vous plaît. Merci d'avance :)
Dex Dave
1
6 et 11 sont les indices auxquels le texte sera inséré dans la chaîne. 6: "<span>"dit: à l'index 6, insérez le texte "<span>". Voulez-vous dire que vous souhaitez utiliser la valeur d'une variable entière comme index d'insertion? Si tel est le cas, essayez quelque chose commevar a=6, text = {}; text[a] = "<span>";
Jake Stoeffler
1
oui je veux utiliser des variables entières comme insertion, votre méthode a fonctionné - merci - c'est ce que j'ai utilisé var a = 6; var b = 11; text = {}; text [a] = "xx"; text [b] = "yy"; - y a-t-il une meilleure façon d'écrire cela
Dex Dave
11

C'est essentiellement ce que fait @ Bass33, sauf que je donne également la possibilité d'utiliser un indice négatif pour compter à partir de la fin. Un peu comme la méthode substr le permet.

// 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);
};

Cas d'utilisation: disons que vous avez des images en taille réelle utilisant une convention de dénomination mais que vous ne pouvez pas mettre à jour les données pour fournir également des URL de vignettes.

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

//    result:  '/images/myimage_thm.jpg'
Ryan Ore
la source
9

Compte tenu de votre exemple actuel, vous pouvez obtenir le résultat en

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

ou

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

mais étant donné que vous pouvez faire de telles hypothèses, vous pourriez aussi bien passer directement à l'exemple de Gullen.

Dans une situation où vous ne pouvez vraiment pas faire d'hypothèses autres que basées sur un index de caractères, alors j'opterais vraiment pour une solution de sous-chaîne.

David Hedlund
la source
6

Je sais que c'est un vieux fil, cependant, voici une approche vraiment efficace.

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

Ce qui est génial, c'est qu'il contraint le contenu du nœud. Donc, si ce nœud était déjà sur le DOM, vous n'auriez pas besoin d'utiliser de sélecteurs de requête ou de mettre à jour le texte interne. Les changements refléteraient en raison de sa liaison.

Si vous aviez besoin d'une chaîne, accédez simplement à la propriété de contenu texte du nœud.

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

Eh bien, nous pouvons utiliser à la fois la méthode de sous-chaîne et de tranche.

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

Le seul problème d'une méthode de sous-chaîne est qu'elle ne fonctionnera pas avec un indice négatif. Il prend toujours l'index de chaîne à partir de la 0e position.

kamal
la source
À quoi sert absIndex?
Enrique Bermúdez
Btw, merci pour la deuxième méthode. Il fonctionne comme un charme!
Enrique Bermúdez
5
function insertString(string, insertion, place) {
  return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}

Donc, pour vous, ce serait insertString("foo baz", "bar", 3);

Évidemment, ce serait une peinture à utiliser car vous devez à chaque fois fournir votre chaîne à la fonction, mais pour le moment je ne sais pas comment en faire quelque chose de plus facile comme un string.replace(insertion, place). L'idée est toujours d'actualité.

Quelklef
la source
4

Vous pouvez utiliser des expressions régulières avec un modèle dynamique .

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

les sorties:

"something      "

Cela remplace les text.lengthespaces blancs au début de la chaîne output. Le RegExpmoyen ^\- début d'une ligne \stout caractère d'espace blanc, {n}fois répété , dans ce cas text.length. Utilisez \\pour \échapper les barres obliques inverses lors de la construction de ce type de motifs à partir de chaînes.

Inopérable
la source
3

une autre solution, couper la chaîne en 2 et mettre une chaîne entre les deux.

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
la source
3

Vous pouvez le faire facilement avec regexp dans une seule ligne de code

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);

"Bonjour belle RegExp!"

Madmadi
la source
2

Utilisation d'une tranche

Vous pouvez utiliser slice(0,index) + str + slice(index). Ou vous pouvez créer une méthode pour cela.

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éthode d'épissure pour les chaînes

Vous pouvez split()la chaîne principale et ajouter puis utiliser 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

Application de splice () à plusieurs index

La méthode prend un tableau de tableaux chaque élément de tableau représentant un seul 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
la source
1

Je voulais comparer la méthode en utilisant la sous-chaîne et la méthode en utilisant la tranche de Base33 et user113716 respectivement, pour ce faire j'ai écrit du code

jetez également un oeil à ce comparaison de performances, sous-chaîne, tranche

Le code que j'ai utilisé crée d'énormes chaînes et insère la chaîne "bar" plusieurs fois dans l'énorme chaîne

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 différence générale de performance est au mieux marginale et les deux méthodes fonctionnent très bien (même sur des chaînes de longueur ~~ 12000000)

Pierre
la source
0
  1. Instancier un tableau à partir de la chaîne
  2. Utiliser l' épissure du tableau #
  3. Stringify à nouveau en utilisant Array # join

Les avantages de cette approche sont doubles:

  1. Facile
  2. Conforme au point de code Unicode

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

Ben Aston
la source