Remplacer plusieurs chaînes par plusieurs autres chaînes


213

J'essaie de remplacer plusieurs mots d'une chaîne par plusieurs autres mots. La chaîne est «J'ai un chat, un chien et une chèvre».

Cependant, cela ne produit pas "J'ai un chien, une chèvre et un chat", mais cela produit plutôt "J'ai un chat, un chat et un chat". Est-il possible de remplacer plusieurs chaînes par plusieurs autres chaînes en même temps en JavaScript, afin que le résultat correct soit produit?

var str = "I have a cat, a dog, and a goat.";
str = str.replace(/cat/gi, "dog");
str = str.replace(/dog/gi, "goat");
str = str.replace(/goat/gi, "cat");

//this produces "I have a cat, a cat, and a cat"
//but I wanted to produce the string "I have a dog, a goat, and a cat".

Je veux remplacer plusieurs mots d'une chaîne par plusieurs autres mots, sans remplacer les mots qui ont déjà été remplacés.
Anderson Green

j'ai une requête différente, que se passe-t-il si je ne sais pas que l'utilisateur va entrer un chat ou un chien ou une chèvre (cela vient au hasard) mais chaque fois que ce genre de mot viendra, je dois le remplacer par disons `` animal ''. comment obtenir ce scénario
Prasanna Sasne

Réponses:


445

Solution spécifique

Vous pouvez utiliser une fonction pour remplacer chacun d'eux.

var str = "I have a cat, a dog, and a goat.";
var mapObj = {
   cat:"dog",
   dog:"goat",
   goat:"cat"
};
str = str.replace(/cat|dog|goat/gi, function(matched){
  return mapObj[matched];
});

exemple jsfiddle

La généraliser

Si vous souhaitez maintenir dynamiquement l'expression régulière et simplement ajouter de futurs échanges à la carte, vous pouvez le faire

new RegExp(Object.keys(mapObj).join("|"),"gi"); 

pour générer l'expression régulière. Alors ça ressemblerait à ça

var mapObj = {cat:"dog",dog:"goat",goat:"cat"};

var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
str = str.replace(re, function(matched){
  return mapObj[matched];
});

Et pour ajouter ou modifier d'autres remplacements, vous pouvez simplement modifier la carte. 

violon avec regex dynamique

Rendre réutilisable

Si vous voulez que ce soit un modèle général, vous pouvez le retirer à une fonction comme celle-ci

function replaceAll(str,mapObj){
    var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}

Donc, vous pouvez simplement passer la str et une carte des remplacements que vous souhaitez à la fonction et cela retournera la chaîne transformée.

violon avec fonction

Pour garantir que Object.keys fonctionne dans les anciens navigateurs, ajoutez un polyfill, par exemple à partir de MDN ou Es5 .


4
Je ne sais pas si je pourrais utiliser cette fonction pour remplacer tous les types de chaînes, car les caractères autorisés dans les chaînes JavaScript ne sont pas les mêmes que ceux autorisés dans les identificateurs JavaScript (tels que les clés utilisées ici) .
Anderson Green

2
vous pouvez utiliser une chaîne arbitraire comme propriété javascript. Ça ne devrait pas avoir d'importance. Vous ne pouvez tout simplement pas utiliser la .notation avec toutes ces propriétés. La notation entre parenthèses fonctionne avec n'importe quelle chaîne.
Ben McCormick

2
Cela fonctionne en effet très bien. J'utilise avec succès cette solution (la «spécifique») pour changer les notations numériques anglaises en européennes (24,973.56 à 24.973,56), en utilisant map={'.': ',', ',': '.'}et regex /\.|,/g.
Sygmoral

5
J'aime cette solution , mais je devais remplacer return mapObj[matched.toLowerCase()];juste return mapObj[matched];que j'utilise des clés cas sensibles mapObj.
Michal Moravcik

2
Vous pouvez échapper aux clés de l'expression régulière: Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Inspiré par cette réponse
robsch

9

Cela peut ne pas répondre à votre besoin exact dans ce cas, mais j'ai trouvé que c'était un moyen utile de remplacer plusieurs paramètres dans les chaînes, comme solution générale. Il remplacera toutes les instances des paramètres, quel que soit le nombre de fois où ils sont référencés:

String.prototype.fmt = function (hash) {
        var string = this, key; for (key in hash) string = string.replace(new RegExp('\\{' + key + '\\}', 'gm'), hash[key]); return string
}

Vous l'invoqueriez comme suit:

var person = '{title} {first} {last}'.fmt({ title: 'Agent', first: 'Jack', last: 'Bauer' });
// person = 'Agent Jack Bauer'

8

Utilisez des éléments numérotés pour éviter de les remplacer à nouveau. par exemple

let str = "I have a %1, a %2, and a %3";
let pets = ["dog","cat", "goat"];

puis

str.replace(/%(\d+)/g, (_, n) => pets[+n-1])

Comment ça marche: -% \ d + trouve les nombres qui viennent après un%. Les crochets capturent le nombre.

Ce nombre (sous forme de chaîne) est le deuxième paramètre, n, de la fonction lambda.

Le + n-1 convertit la chaîne en nombre puis 1 est soustrait pour indexer le tableau pets.

Le nombre% est ensuite remplacé par la chaîne à l'index du tableau.

Le / g provoque l'appel répété de la fonction lambda avec chaque numéro qui est ensuite remplacé par une chaîne du tableau.

En JavaScript moderne: -

replace_n=(str,...ns)=>str.replace(/%(\d+)/g,(_,n)=>ns[n-1])

Intéressant. Pouvez-vous expliquer la logique de la fonction de remplacement?
Eric Hepperle - CodeSlayer2010

5

Cela a fonctionné pour moi:

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

function replaceAll(str, map){
    for(key in map){
        str = str.replaceAll(key, map[key]);
    }
    return str;
}

//testing...
var str = "bat, ball, cat";
var map = {
    'bat' : 'foo',
    'ball' : 'boo',
    'cat' : 'bar'
};
var new = replaceAll(str, map);
//result: "foo, boo, bar"


Ne fonctionne pas si la chaîne contient des caractères d'expression régulière.
Roemer

A propos de "ne pas étendre ...": j'ai étendu ma chaîne pour comparer deux chaînes d'égalité, insensible à la casse. Cette fonctionnalité n'est pas fournie par String, mais elle pourrait l'être un jour, ce qui pourrait entraîner la rupture de mes applications. Existe-t-il un moyen de "sous-classe" ou "étendre" String pour inclure une telle fonction en toute sécurité, ou dois-je simplement définir une nouvelle fonction à deux arguments dans le cadre de ma bibliothèque d'applications?
David Spector

4

en utilisant Array.prototype.reduce () :

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence = 'plants are smart'

arrayOfObjects.reduce(
  (f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence
)

// as a reusable function
const replaceManyStr = (obj, sentence) => obj.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

const result = replaceManyStr(arrayOfObjects , sentence1)

Exemple

// /////////////    1. replacing using reduce and objects

// arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence)

// replaces the key in object with its value if found in the sentence
// doesn't break if words aren't found

// Example

const arrayOfObjects = [
  { plants: 'men' },
  { smart:'dumb' },
  { peace: 'war' }
]
const sentence1 = 'plants are smart'
const result1 = arrayOfObjects.reduce((f, s) => `${f}`.replace(Object.keys(s)[0], s[Object.keys(s)[0]]), sentence1)

console.log(result1)

// result1: 
// men are dumb


// Extra: string insertion python style with an array of words and indexes

// usage

// arrayOfWords.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence)

// where arrayOfWords has words you want to insert in sentence

// Example

// replaces as many words in the sentence as are defined in the arrayOfWords
// use python type {0}, {1} etc notation

// five to replace
const sentence2 = '{0} is {1} and {2} are {3} every {5}'

// but four in array? doesn't break
const words2 = ['man','dumb','plants','smart']

// what happens ?
const result2 = words2.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence2)

console.log(result2)

// result2: 
// man is dumb and plants are smart every {5}

// replaces as many words as are defined in the array
// three to replace
const sentence3 = '{0} is {1} and {2}'

// but five in array
const words3 = ['man','dumb','plant','smart']

// what happens ? doesn't break
const result3 = words3.reduce((f, s, i) => `${f}`.replace(`{${i}}`, s), sentence3)

console.log(result3)

// result3: 
// man is dumb and plants


Meilleure réponse. Mais y a-t-il une raison d'utiliser ${f}au lieu de f pour la valeur cumulée?
David Spector

1
Si vous souhaitez que TOUTES les chaînes données soient remplacées, pas seulement la première, ajoutez l'indicateur g: "const result1 = arrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [ 0], 'g'), s [Object.keys (s) [0]]), phrase1) "
David Spector

2

Juste au cas où quelqu'un se demanderait pourquoi la solution de l'affiche originale ne fonctionne pas:

var str = "I have a cat, a dog, and a goat.";

str = str.replace(/cat/gi, "dog");
// now str = "I have a dog, a dog, and a goat."

str = str.replace(/dog/gi, "goat");
// now str = "I have a goat, a goat, and a goat."

str = str.replace(/goat/gi, "cat");
// now str = "I have a cat, a cat, and a cat."

ha ha ... bien analysé ... thumbsup
Deepa MG

1

fonction régulière de l'utilisateur pour définir le modèle à remplacer, puis utiliser la fonction de remplacement pour travailler sur la chaîne d'entrée,

var i = new RegExp('"{','g'),
    j = new RegExp('}"','g'),
    k = data.replace(i,'{').replace(j,'}');

Si vous ne savez pas sauter, mais ne dites pas que c'est la mauvaise réponse. Mon cas "{" a ": 1," b ": 2}" comme ça est là, j'ai utilisé pour remplacer la façon ci-dessus. Si cela aide les autres s'ils veulent pour les autres, la réponse n'est pas seulement pour vous. @Carr
KARTHIKEYAN.A

Encore une fois, vous venez de fournir une réponse dénuée de sens, ce que vous faites est que le demandeur peut déjà faire dans la question, cette réponse induira en erreur les gens qu'ils peuvent penser nouveaux et utiliser l' RegExpobjet pourrait résoudre le problème
Carr

Dans ce cas, vous avez toujours le même problème que la question du demandeur lorsque vous le faitesvar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

Avec mon package à remplacement unique , vous pouvez effectuer les opérations suivantes:

const replaceOnce = require('replace-once')

var str = 'I have a cat, a dog, and a goat.'
var find = ['cat', 'dog', 'goat']
var replace = ['dog', 'goat', 'cat']
replaceOnce(str, find, replace, 'gi')
//=> 'I have a dog, a goat, and a cat.'

Ce package est incroyable :) Fonctionne exactement comme je
m'y

1
    var str = "I have a cat, a dog, and a goat.";

    str = str.replace(/goat/i, "cat");
    // now str = "I have a cat, a dog, and a cat."

    str = str.replace(/dog/i, "goat");
    // now str = "I have a cat, a goat, and a cat."

    str = str.replace(/cat/i, "dog");
    // now str = "I have a dog, a goat, and a cat."

3
L'OP a demandé "Est-il possible de remplacer plusieurs chaînes par plusieurs autres chaînes en même temps ". Il s'agit de trois étapes distinctes.
LittleBobbyTables - Au Revoir

1

Vous pouvez rechercher et remplacer une chaîne à l'aide de délimiteurs.

var obj = {
  'firstname': 'John',
  'lastname': 'Doe'
}

var text = "My firstname is {firstname} and my lastname is {lastname}"

console.log(mutliStringReplace(obj,text))

function mutliStringReplace(object, string) {
      var val = string
      var entries = Object.entries(object);
      entries.forEach((para)=> {
          var find = '{' + para[0] + '}'
          var regExp = new RegExp(find,'g')
       val = val.replace(regExp, para[1])
    })
  return val;
}


0
String.prototype.replaceSome = function() {
    var replaceWith = Array.prototype.pop.apply(arguments),
        i = 0,
        r = this,
        l = arguments.length;
    for (;i<l;i++) {
        r = r.replace(arguments[i],replaceWith);
    }
    return r;
}

/ * méthode replaceSome pour les chaînes qu'il faut autant, autant d'arguments que nous voulons et les remplace tous par le dernier argument pour lequel nous avons spécifié 2013 CopyRights enregistré pour: Max Ahmed voici un exemple:

var string = "[hello i want to 'replace x' with eat]";
var replaced = string.replaceSome("]","[","'replace x' with","");
document.write(string + "<br>" + replaced); // returns hello i want to eat (without brackets)

* /

jsFiddle: http://jsfiddle.net/CPj89/


0
<!DOCTYPE html>
<html>
<body>



<p id="demo">Mr Blue 
has a           blue house and a blue car.</p>

<button onclick="myFunction()">Try it</button>

<script>
function myFunction() {
    var str = document.getElementById("demo").innerHTML;
    var res = str.replace(/\n| |car/gi, function myFunction(x){

if(x=='\n'){return x='<br>';}
if(x==' '){return x='&nbsp';}
if(x=='car'){return x='BMW'}
else{return x;}//must need



});

    document.getElementById("demo").innerHTML = res;
}
</script>

</body>
</html>

0

J'ai écrit ce package npm stringinject https://www.npmjs.com/package/stringinject qui vous permet de faire ce qui suit

var string = stringInject("this is a {0} string for {1}", ["test", "stringInject"]);

qui remplacera les {0} et {1} par les éléments du tableau et renverra la chaîne suivante

"this is a test string for stringInject"

ou vous pouvez remplacer les espaces réservés par des clés d'objet et des valeurs comme ceci:

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

"My username is tjcafferkey on Github" 

0

Vous pouvez utiliser https://www.npmjs.com/package/union-replacer à cet effet. Il s'agit essentiellement d'une string.replace(regexp, ...)contrepartie, qui permet à plusieurs remplacements de se produire en une seule passe tout en préservant la pleine puissance destring.replace(...) .

Divulgation: je suis l'auteur. La bibliothèque a été développée pour prendre en charge des remplacements configurables par l'utilisateur plus complexes et elle traite toutes les choses problématiques comme les groupes de capture, les références arrières et les remplacements de fonctions de rappel.

Les solutions ci-dessus sont cependant assez bonnes pour des remplacements de chaînes exacts.


0

en utilisant la fonction prototype, nous pouvons remplacer facilement en passant un objet avec des clés et des valeurs et du texte remplaçable

String.prototype.replaceAll=function(obj,keydata='key'){
 const keys=keydata.split('key');
 return Object.entries(obj).reduce((a,[key,val])=> a.replace(`${keys[0]}${key}${keys[1]}`,val),this)
}

const data='hids dv sdc sd ${yathin} ${ok}'
console.log(data.replaceAll({yathin:12,ok:'hi'},'${key}'))


-1

J'ai développé un peu @BenMcCormicks. Il travaillait pour des cordes régulières mais pas si j'avais échappé à des caractères ou à des caractères génériques. Voici ce que j'ai fait

str = "[curl] 6: blah blah 234433 blah blah";
mapObj = {'\\[curl] *': '', '\\d: *': ''};


function replaceAll (str, mapObj) {

    var arr = Object.keys(mapObj),
        re;

    $.each(arr, function (key, value) {
        re = new RegExp(value, "g");
        str = str.replace(re, function (matched) {
            return mapObj[value];
        });
    });

    return str;

}
replaceAll(str, mapObj)

renvoie "bla bla 234433 bla bla"

De cette façon, il correspondra à la clé dans mapObj et non au mot correspondant '


// sans valeur: replaceAll ("J'ai un chat, un chien et une chèvre.", {cat: "chien", chien: "chèvre", chèvre: "chat"}) // produit: "J'ai un chat , un chat et un chat. "
devon

-3

Solution avec Jquery (incluez d'abord ce fichier): remplacez plusieurs chaînes par plusieurs autres chaînes:

var replacetext = {
    "abc": "123",
    "def": "456"
    "ghi": "789"
};

$.each(replacetext, function(txtorig, txtnew) {
    $(".eng-to-urd").each(function() {
        $(this).text($(this).text().replace(txtorig, txtnew));
    });
});

Cette solution nécessite-t-elle JQuery?
Anderson Green

balise javascript ajoutée en question, et jquery est une bibliothèque de javascript.
Super Model

2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmm que la logique est désactivée, cela devrait être l'inverse, et aussi juste un avertissement - à partir des informations de balise javascript: " À moins qu'une autre balise pour un framework / bibliothèque soit également incluse, une réponse JavaScript pure est attendue. "
Traxo

@Anderson Green, oui jquery nécessaire pour le script ci-dessus.
Super Model

@ Traxo, dans la plupart des applications Web, nous utilisons un framework (matériel bootstrap / google). Jquery inclut dans tous les cadres modernes. Ainsi, jquery est un élément nécessaire pour les applications Web.
Super Model
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.