Sostituisci più stringhe con più altre stringhe


213

Sto cercando di sostituire più parole in una stringa con più altre parole. La stringa è "Ho un gatto, un cane e una capra".

Tuttavia, questo non produce "Ho un cane, una capra e un gatto", ma invece produce "Ho un gatto, un gatto e un gatto". È possibile sostituire più stringhe con più altre stringhe contemporaneamente in JavaScript, in modo da produrre il risultato corretto?

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".

Voglio sostituire più parole in una stringa con più altre parole, senza sostituire le parole che sono già state sostituite.
Anderson Green

ho una domanda diversa, e se non sapessi che l'utente entrerà nel gatto, nel cane o nella capra (questa viene in modo casuale) ma ogni volta che questa parola verrà, devo sostituirla con diciamo "animale". come ottenere questo scenario
Prasanna Sasne il

Risposte:


445

Soluzione specifica

È possibile utilizzare una funzione per sostituire ciascuna.

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

esempio jsfiddle

Generalizzandolo

Se vuoi mantenere dinamicamente la regex e semplicemente aggiungere futuri scambi alla mappa, puoi farlo

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

per generare la regex. Quindi sarebbe così

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

E per aggiungere o modificare altri rimpiazzi puoi semplicemente modificare la mappa. 

violino con regex dinamico

Rendendolo riutilizzabile

Se vuoi che questo sia un modello generale, puoi estrarlo a una funzione come questa

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

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

Quindi potresti semplicemente passare la str e una mappa delle sostituzioni che vuoi alla funzione e restituirebbe la stringa trasformata.

violino con funzione

Per assicurarsi che Object.keys funzioni nei browser meno recenti, aggiungere un polyfill, ad esempio da MDN o Es5 .


4
Non sono sicuro di poter utilizzare questa funzione per sostituire tutti i tipi di stringhe, poiché i caratteri consentiti nelle stringhe JavaScript non sono gli stessi consentiti negli identificatori JavaScript (come le chiavi utilizzate qui) .
Anderson Green,

2
puoi usare una stringa arbitraria come proprietà javascript. Non dovrebbe importare. Non puoi semplicemente usare la .notazione con tutte queste proprietà. La notazione delle parentesi funziona con qualsiasi stringa.
Ben McCormick,

2
Funziona davvero alla grande. Sto usando con successo questa soluzione (quella "specifica") per cambiare le notazioni numeriche inglesi in notazioni europee (da 24.973,56 a 24.973,56), usando map={'.': ',', ',': '.'}e regex /\.|,/g.
Sygmoral,

5
Adoro questa soluzione, ma ho dovuto sostituirla return mapObj[matched.toLowerCase()];solo return mapObj[matched];da quando utilizzo chiavi sensibili al maiuscolo / minuscolo mapObj.
Michal Moravcik,

2
Si consiglia di fuggire le chiavi per l'espressione regolare: Object.keys(mapObj).map(key => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join('|'). Ispirato da questa risposta
robsch il

9

Questo potrebbe non soddisfare l'esatta necessità in questo caso, ma ho trovato questo un modo utile per sostituire più parametri nelle stringhe, come soluzione generale. Sostituirà tutte le istanze dei parametri, indipendentemente dal numero di volte in cui sono referenziati:

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

Lo invocheresti come segue:

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

8

Utilizzare gli elementi numerati per impedire la sostituzione di nuovo. per esempio

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

poi

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

Come funziona: -% \ d + trova i numeri che seguono una%. Le parentesi catturano il numero.

Questo numero (come stringa) è il secondo parametro, n, alla funzione lambda.

+ N-1 converte la stringa nel numero, quindi viene sottratto 1 per indicizzare l'array di animali domestici.

Il numero% viene quindi sostituito con la stringa nell'indice dell'array.

/ G fa sì che la funzione lambda venga chiamata ripetutamente con ogni numero che viene quindi sostituito con una stringa dall'array.

Nel moderno JavaScript: -

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

Interessante. Puoi spiegare la logica nella funzione di sostituzione?
Eric Hepperle - CodeSlayer2010,

5

Questo ha funzionato per me:

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"


Non funziona se la stringa contiene caratteri regex.
Roemer

Informazioni su "non estendere ...": ho esteso la mia stringa per confrontare due stringhe per uguaglianza, senza distinzione tra maiuscole e minuscole. Questa funzionalità non è fornita da String, ma potrebbe essere un giorno, il che potrebbe causare l'interruzione delle mie app. Esiste un modo per "sottoclassare" o "estendere" la stringa per includere una tale funzione in modo sicuro, o dovrei semplicemente definire una nuova funzione a due argomenti come parte della mia libreria di app?
David Spector,

4

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

Esempio

// /////////////    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


Migliore risposta. Ma c'è un motivo da usare ${f}invece di f per il valore accumulato?
David Spector,

1
Se vuoi che TUTTE le stringhe date vengano sostituite, non solo la prima, aggiungi il flag g: "const result1 = arrayOfObjects.reduce ((f, s) => ${f}.replace (new RegExp (Object.keys (s) [ 0], 'g'), s [Object.keys (s) [0]]), frase1) "
David Spector

2

Nel caso in cui qualcuno si stia chiedendo perché la soluzione del poster originale non funziona:

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."

ah ah ... ben analizzato ... pollice
alzato

1

funzione regolare dell'utente per definire il modello da sostituire e quindi utilizzare la funzione di sostituzione per lavorare sulla stringa di input,

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

Se non sei a conoscenza salta, ma non dire che è la risposta sbagliata. Il mio caso "{" a ": 1," b ": 2}" come quello è lì che ho usato per sostituire il modo sopra. Se aiuta gli altri se vogliono per gli altri, la risposta non è solo per te. @Carr
KARTHIKEYAN.A,

Ancora una volta, hai appena fornito una risposta insignificante, quello che fai è che chi fa la domanda può già fare nella domanda, questa risposta fuorvierà le persone che potrebbero pensare di nuovo e utilizzare l' RegExpoggetto potrebbe risolvere il problema
Carr

In questo caso, hai ancora lo stesso problema della domanda di Asker quando lo faivar i = new RegExp('}','g'), j = new RegExp('{','g'), k = data.replace(i,'{').replace(j,'}');
Carr

1

Con il mio pacchetto di sostituzione , puoi fare quanto segue:

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.'

Questo pacchetto è fantastico :) Funziona esattamente come mi aspettavo
Vishnu Prassad il

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 ha chiesto "È possibile sostituire più stringhe con più altre stringhe contemporaneamente ". Si tratta di tre passaggi separati.
LittleBobbyTables - Au Revoir,

1

È possibile trovare e sostituire la stringa utilizzando i delimitatori.

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

/ * replace Alcuni metodi per le stringhe che servono, tanti argomenti come vogliamo e li sostituisce con l'ultimo argomento che abbiamo specificato 2013 CopyRights salvato per: Max Ahmed questo è un esempio:

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

Ho scritto questo pacchetto npm stringinject https://www.npmjs.com/package/stringinject che ti permette di fare quanto segue

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

che sostituirà {0} e {1} con gli elementi dell'array e restituirà la seguente stringa

"this is a test string for stringInject"

oppure potresti sostituire i segnaposto con chiavi oggetto e valori in questo modo:

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

"My username is tjcafferkey on Github" 

0

A tale scopo è possibile utilizzare https://www.npmjs.com/package/union-replacer . È fondamentalmente una string.replace(regexp, ...)controparte, che consente a più sostituzioni di avvenire in un passaggio preservando la piena potenza distring.replace(...) .

Divulgazione: sono l'autore. La libreria è stata sviluppata per supportare sostituzioni configurabili dall'utente più complesse e affronta tutte le problematiche come gruppi di acquisizione, backreferenze e sostituzioni di funzioni di callback.

Le soluzioni sopra sono abbastanza buone per esatte sostituzioni di stringhe.


0

usando la funzione prototipo possiamo sostituire facilmente passando l'oggetto con chiavi e valori e testo sostituibile

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

Ho ampliato un po 'su @BenMcCormicks. Ha lavorato per stringhe regolari, ma non se fossi sfuggito a personaggi o caratteri jolly. Ecco cosa ho fatto

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)

restituisce "blah blah 234433 blah blah"

In questo modo corrisponderà alla chiave nella mappaObj e non alla parola corrispondente "


// inutile: replaceAll ("I have a cat, a dog and a goat.", {cat: "dog", dog: "goat", goat: "cat"}) // produce: "I have a cat , un gatto e un gatto ".
Devon,

-3

Soluzione con Jquery (includere prima questo file): sostituire più stringhe con più altre stringhe:

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

Questa soluzione richiede JQuery?
Anderson Green,

tag javascript aggiunto in questione e jquery è un libarario di javascript.
Super Model

2
@Super javascript tag added in question, and jquery is a libarary of javascript.Hmmm che la logica è disattivata, dovrebbe essere al contrario, e anche solo un avvertimento - dalle informazioni sui tag javascript: " A meno che non sia incluso anche un altro tag per un framework / libreria, è prevista una risposta JavaScript pura. "
Traxo

@Anderson Green, sì jquery necessario per lo script sopra.
Super Model

@ Traxo, nella maggior parte delle applicazioni Web utilizziamo framework (materiale bootstrap / google). Jquery include in tutti i quadri moderni. Quindi, jquery è l'elemento necessario per le applicazioni web.
Super Model
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.