プレースホルダーと置換オブジェクトを使用してJavaScript文字列をフォーマットしますか?


92

私は言う文字列を持っています: My Name is %NAME% and my age is %AGE%.

%XXX%プレースホルダーです。そこで、オブジェクトの値を置き換える必要があります。

オブジェクトは次のようになります: {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"}

オブジェクトを解析し、文字列を対応する値に置き換える必要があります。そのため、最終的な出力は次のようになります。

私の名前はマイクで、年齢は26歳です。

すべては、純粋なjavascriptまたはjqueryを使用して実行する必要があります。


2
それは配列というよりもオブジェクトのように見えます
Joel Coehoorn 2011年

3
これまでに何を試しましたか?string .replace()メソッドを見たことがありますか?(また、そこには配列がなく、オブジェクトがあります。)
nnnnnn 2011年

1
それはかなり醜いです。きっとあなたも同じように仕えられる{NAME: "Mike", AGE: 26, EVENT: 20}でしょう?もちろん、これらのキーは入力文字列のパーセント記号で予約されているように見える必要があります。
davidchambers 2011年

回答:


151

元の質問の要件は、任意の置換キーの実行時処理であるように見えるため、文字列補間の恩恵を受けられないことは明らかです。

ただし、文字列補間を行う必要がある場合は、次を使用できます。

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

文字列を区切るバッククォートに注意してください。これらは必須です。


特定のOPの要件に適合する回答についてはString.prototype.replace()、代替に使用できます。

次のコードはすべての一致を処理し、置換なしの一致には触れません(置換値がすべて文字列である限り、そうでない場合は、以下を参照してください)。

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

一部の置換が文字列でない場合は、最初にそれらがオブジェクトに存在することを確認してください。例のような形式、つまりパーセンテージ記号でラップされている場合は、in演算子をこれを実現。

jsFiddle

ただし、フォーマットに特別なフォーマット、つまり文字列がなく、置換オブジェクトにnullプロトタイプがない場合は、次を使用してください。Object.prototype.hasOwnProperty()される可能性のある部分文字列がプロトタイプのプロパティ名と衝突しないことが保証されない限りください。

jsFiddle

そうしないと、置換文字列が'hasOwnProperty'であった場合、結果として文字列が台無しになります。

jsFiddle


注意点として、あなたが呼ばれるべきではありません。replacementsObjectArray


2
+1。いいね。あなたはケースreturn replacements[all] || allをカバーするために言いたいかもしれませんが%NotInReplacementsList%
nnnnnn 2011年

6
置換値が偽の場合、これは機能しません。したがって、次のreturnステートメントを使用することをおreturn all in params ? params[all] : all;
勧めし

@MichaelHärtlあなたの置き換えはすべて文字列であるべきではありませんか?空の文字列に置き換えたい場合は、他の方法で確認することをお勧めします。
アレックス2015

1
@alex置換が整数、さらには0。である可能性がある状況がありました。この場合、それは機能しませんでした。
マイケル・ハートル

@MichaelHärtlそのケースをカバーするように更新されました。
アレックス2016年

24

ES6テンプレートリテラルを使用するのはどうですか?

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

テンプレートリテラルの詳細...


5
OPのようなプレースホルダーを持つオブジェクトがある場合、文字列補間はどのように役立ちますか?
アレックス

チャームのように機能します!私のプレースホールディングの問題に対する最も実用的な解決策、完璧です。
BAERUS

このソリューションは、ランタイムの置き換えでは機能しません
Thierry J.

13

JQuery(jquery.validate.js)を使用して、簡単に機能させることができます。

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

または、その機能だけを使用したい場合は、その関数を定義して、次のように使用できます。

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

jquery.validate.jsチームの功績


1
これだけのためにこのプラグインをロードしたくないことは間違いありませんが、私はすでにこれを使用してページ上のフォームを検証しています...ヒントをありがとう!
nabrown 2015

1
数値ごとに正規表現を作成するのはかなり非効率的です。すべての数値を一致させてから、値が配列で見つかった場合は置き換えたほうがよいでしょう。
アレックス2016年

興味のある人は、ここでそれが起こります: github.com/jquery-validation/jquery-validation/blob/master/src/…–
Raphael C

1
+とても素敵です...そして$.eachあなたが作ることができるString.prototype.format=function(p){var s=this,r=function(v,i){s=s.replace(new RegExp("\\{"+i+"\\}","g"),v);};p.forEach(r);return s;}ので、そのためだけにjqueryを含める必要はありません;)
Larphoid 2018

11

最新のブラウザと同様に、プレースホルダーはCスタイルの関数と同様に新しいバージョンのChrome / Firefoxでサポートされていますprintf()

プレースホルダー:

  • %s ストリング。
  • %d%i整数。
  • %f 浮動小数点数。
  • %o オブジェクトのハイパーリンク。

例えば

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

ところで、出力を確認するには:

  • Chromeでは、ショートカットCtrl + Shift + JまたはF12をして開発者ツールを開きます。
  • Firefoxでは、ショートカットを使用するCtrl + Shift + KF12、開発者ツールを開きます。

@ Update-nodejsサポート

nodejsはサポートしていないようですが%f、代わり%dにnodejsで使用できます。with %dnumberは、整数だけでなく浮動小数点数として出力されます。



5

次のようなカスタム置換機能を使用できます。

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

function substitute(str, data) {
    var output = str.replace(/%[^%]+%/g, function(match) {
        if (match in data) {
            return(data[match]);
        } else {
            return("");
        }
    });
    return(output);
}

var output = substitute(str, replaceData);

ここで動作することがわかります:http//jsfiddle.net/jfriend00/DyCwk/


1
かっこいい、アレックスはほとんど同じことをしましたが、コードの行数が少なくなりました(ただし、三項演算子はif..elseよりも遅い可能性があります)。
RobG 2011年

ねえ、私はあなたに+1を与えました!あなたは両方とも置換機能を実行しました。あなたの機能はまったく同じではありませんが、かなり似ています。あなたの正規表現も異なります。OPは%%または$$などを区切り文字として使用する方が良いでしょう-単一の%または%は通常文字列で発生する可能性がありますが、doubleはありそうにありません。
RobG 2011年

4

次のように%sプレースホルダーを置き換えるなど、console.logに近い処理を実行する場合

>console.log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright")
>Hello Loreto how are you today is everything allright?

私はこれを書いた

function log() {
  var args = Array.prototype.slice.call(arguments);
  var rep= args.slice(1, args.length);
  var i=0;
  var output = args[0].replace(/%s/g, function(match,idx) {
    var subst=rep.slice(i, ++i);
    return( subst );
  });
   return(output);
}
res=log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright");
document.getElementById("console").innerHTML=res;
<span id="console"/>

あなたは得るでしょう

>log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright")
>"Hello Loreto how are you today is everything allright?"

更新

String.prototype文字列変換を処理するときに役立つ単純なバリアントを追加しました。これは次のとおりです。

String.prototype.log = function() {
    var args = Array.prototype.slice.call(arguments);
    var rep= args.slice(0, args.length);
    var i=0;
    var output = this.replace(/%s|%d|%f|%@/g, function(match,idx) {
      var subst=rep.slice(i, ++i);
      return( subst );
    });
    return output;
   }

その場合、あなたはします

"Hello %s how are you %s is everything %s?".log("Loreto", "today", "allright")
"Hello Loreto how are you today is everything allright?"

ここでこのバージョンを試してください


2
私はプロトタイプなしであなたの関数のバリエーションを作ったformatMessage(message: string, values: string[]) { let i = 0; return message.replace(/%\w+%/g, (match, idx) => { return values[i++]; }); } 、これがために置き換える値とルックスの形式と配列へのメッセージを取る%SOME_VALUE%
バクー

3

現在、この動作に対するJavascriptのネイティブソリューションはまだありません。タグ付けされたテンプレートは関連するものですが、それを解決しないでください。

ここに、置換用のオブジェクトを使用したalexのソリューションのリファクタリングがあります。

このソリューションでは、(の代わりに)テンプレートリテラルのネイティブJavascript補間と同様に、プレースホルダーに矢印関数と同様の構文を使用します。また、置換の名前に区切り文字()を含める必要はありません{}%%%

説明と削減の2つのフレーバーがあります。

記述的解決策:

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

削減されたソリューション:

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


1
これに感謝します。プレースホルダー文字列とオブジェクトを次のようにマージするための一般的なソリューションがあるのは素晴らしいことです
Carlos P

@CarlosP、それは一般的な解決策を持つという考えです。しかし、それは一般的な使用例であるため、その言語に固有のものでなければならないと思います。
AMS777

2

これにより、まさにそれを行うことができます

NPM:https//www.npmjs.com/package/stringinject

GitHub:https//github.com/tjcafferkey/stringinject

次の手順を実行します。

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

// My username is tjcafferkey on Git

2
しかし、es6でそれを行うことができるので、それはおそらく少しやり過ぎですか?
ionicBurger 2018年

1
これにより、文字列を1つの形式で1つの場所に保存し、後で1つの関数のみを使用して対応するアイテムを置き換えることができます。私の知る限り、これはes6テンプレートリテラルでは実行できません。これの使用法は、たとえば、他の場所で文字列を消費し、そこに目的の値を挿入する翻訳文字列です。
ヨハン・パーソン

2

実行時にes6テンプレートリテラルを動的に使用してこれを行う別の方法を次に示します。

const str = 'My name is ${name} and my age is ${age}.'
const obj = {name:'Simon', age:'33'}


const result = new Function('const {' + Object.keys(obj).join(',') + '} = this.obj;return `' + str + '`').call({obj})

document.body.innerHTML = result


1

簡単な例として:

var name = 'jack';
var age = 40;
console.log('%s is %d yrs old',name,age);

出力は次のとおりです。

ジャックは40歳です


7
コンソールにログを記録する以外に何かをしたいのでなければ、それは素晴らしいことです。
アレックス2016年

13
そうではないconsole.logですか?
drzaus 2016

0
const stringInject = (str = '', obj = {}) => {
  let newStr = str;
  Object.keys(obj).forEach((key) => {
    let placeHolder = `#${key}#`;
    if(newStr.includes(placeHolder)) {
      newStr = newStr.replace(placeHolder, obj[key] || " ");
    }
  });
  return newStr;
}
Input: stringInject("Hi #name#, How are you?", {name: "Ram"});
Output: "Hi Ram, How are you?"

0

文字列を簡単にフォーマットできるコードを書きました。

この機能を使用してください。

function format() {
    if (arguments.length === 0) {
        throw "No arguments";
    }
    const string = arguments[0];
    const lst = string.split("{}");
    if (lst.length !== arguments.length) {
        throw "Placeholder format mismatched";
    }
    let string2 = "";
    let off = 1;
    for (let i = 0; i < lst.length; i++) {
        if (off < arguments.length) {
            string2 += lst[i] + arguments[off++]
        } else {
            string2 += lst[i]
        }
    }
    return string2;
}

format('My Name is {} and my age is {}', 'Mike', 26);

出力

私の名前はマイクです。年齢は26歳です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.