jquery - Formatera en JavaScript-sträng med platshållare och ett objekt med ersättningar?


Jag har en sträng med till exempel: My Name is %NAME% and my age is %AGE%.

%XXX% är platshållare. Vi behöver ersätta värden därifrån från ett objekt.

Objektet ser ut som: {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"}

Jag behöver analysera objektet och ersätta strängen med motsvarande värden. Så att det slutliga resultatet blir:

Mitt namn är Mike och min ålder är 26.

Hela saken måste göras antingen med ren JavaScript eller jQuery.

Svar #1

Kravet i den ursprungliga frågan kunde tydligt inte dra nytta av stränginterpolering, eftersom det verkar som om det handlar om bearbetning vid körning av godtyckliga ersättningsnycklar.

Men, om du bara måste göra stränginterpolation, kan du använda:

const str = `My name is ${replacements.name} and my age is ${replacements.age}.`

Notera backticks som avgränsar strängen, de är obligatoriska.

För ett svar som passar den specifika OP:s krav, kan du använda String.prototype.replace() för ersättningarna.

Följande kod kommer att hantera alla matchningar och inte röra de utan ersättning (så länge dina ersättningsvärden alla är strängar, om inte, se nedan).

var replacements = {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"},
    str = 'My Name is %NAME% and my age is %AGE%.';

str = str.replace(/%\w+%/g, function(all) {
   return replacements[all] || all;
});

jsFiddle.

Om några av dina ersättningar inte är strängar, se till att de finns i objektet först. Om du har ett format som exemplet, dvs. inneslutet i procenttecken, kan du använda in-operatorn för att uppnå detta.

jsFiddle.

Men om ditt format inte har ett speciellt format, t.ex. vilken sträng som helst, och ditt ersättningsobjekt inte har en null-prototyp, använd Object.prototype.hasOwnProperty(), om du inte kan garantera att inga av dina potentiella ersatta understrängar kommer att krocka med egenskapsnamn på prototypen.

jsFiddle.

Annars, om din ersättningssträng var 'hasOwnProperty', skulle du få en resulterande rörig sträng.

jsFiddle.

Som en sidonotering borde du kallas replacements ett Object, inte ett Array.

Svar #2

Vad sägs om att använda ES6-mallsträngar?

var a = "cat";
var b = "fat";
console.log(`my ${a} is ${b}`); //notice back-ticked string

Mer om mallsträngar...

Svar #3

För närvarande finns det fortfarande ingen inbyggd lösning i Javascript för detta beteende. Taggade mallar är något relaterat, men löser det inte.

Här finns en omstrukturering av Alex lösning med ett objekt för ersättningar.

Lösningen använder pilfunktioner och en liknande syntax för platshållarna som den inbyggda Javascript-interpolation i mallsträngar ({} istället för %%). Dessutom finns det inget behov av att inkludera avgränsare (%) i namnen på ersättningarna.

Det finns två varianter (tre med uppdateringen): beskrivande, reducerad, elegant reducerad med grupper.

Beskrivande lösning:

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '26',
};

const string = stringWithPlaceholders.replace(
  /{\w+}/g,
  placeholderWithDelimiters => {
    const placeholderWithoutDelimiters = placeholderWithDelimiters.substring(
      1,
      placeholderWithDelimiters.length - 1,
    );
    const stringReplacement = replacements[placeholderWithoutDelimiters] || placeholderWithDelimiters;
    return stringReplacement;
  },
);

console.log(string);

Reducerad lösning:

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '26',
};

const string = stringWithPlaceholders.replace(/{\w+}/g, placeholder =>
  replacements[placeholder.substring(1, placeholder.length - 1)] || placeholder
);

console.log(string);

UPPDATERA 2020-12-10

Elegant reducerad lösning med grupper, som föreslagits av @Kade i kommentarerna:

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '26',
};

const string = stringWithPlaceholders.replace(
  /{(\w+)}/g, 
  (placeholderWithDelimiters, placeholderWithoutDelimiters) =>
    replacements[placeholderWithoutDelimiters] || placeholderWithDelimiters
);

console.log(string);

UPPDATERA 2021-01-21

Stöd en tom sträng som ersättning, som föreslagits av @Jesper i kommentarerna:

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '',
};

const string = stringWithPlaceholders.replace(
  /{(\w+)}/g, 
  (placeholderWithDelimiters, placeholderWithoutDelimiters) =>
  replacements.hasOwnProperty(placeholderWithoutDelimiters) ? 
    replacements[placeholderWithoutDelimiters] : placeholderWithDelimiters
);

console.log(string);

Svar #4

Du kan använda JQuery (jquery.validate.js) för att få det att fungera enkelt.

$.validator.format("My name is {0}, I'm {1} years old",["Bob","23"]);

Eller om du bara vill använda den funktionen kan du definiera den funktionen och bara använda den som

function format(source, params) {
    $.each(params,function (i, n) {
        source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
    })
    return source;
}
alert(format("{0} is a {1}", ["Michael", "Guy"]));

kredit till jquery.validate.js-teamet

Svar #5

Precis som med moderna webbläsare stöds platshållare av den nya versionen av Chrome/Firefox, på liknande sätt som C-stilens funktion printf().

Platshållare:

  • %s Sträng.
  • %d,%i Heltal.
  • %f Flyttal.
  • %o Objekt hyperlänk.

t.ex.

console.log("generation 0:\t%f, %f, %f", a1a1, a1a2, a2a2);

Förresten, för att se resultatet:

  • I Chrome, använd kortkommandot Ctrl + Shift + J eller F12 för att öppna utvecklarverktyget.
  • I Firefox, använd kortkommandot Ctrl + Shift + K eller F12 för att öppna utvecklarverktyget.

@Uppdatering - nodejs-stöd

Verkar som att nodejs inte stöder %f, istället kan man använda %d i nodejs. Med %d kommer numret att skrivas ut som ett flyttal, inte bara heltal.

Svar #6

Använd bara replace()

var values = {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"};
var substitutedString = "My Name is %NAME% and my age is %AGE%.".replace("%NAME%", $values["%NAME%"]).replace("%AGE%", $values["%AGE%"]);

Relaterade artiklar