相当于 Python 的 format()函数的 JavaScript?

Python 有这个漂亮的函数来转动它:

bar1 = 'foobar'
bar2 = 'jumped'
bar3 = 'dog'


foo = 'The lazy ' + bar3 + ' ' + bar2 ' over the ' + bar1
# The lazy dog jumped over the foobar

变成这样:

bar1 = 'foobar'
bar2 = 'jumped'
bar3 = 'dog'


foo = 'The lazy {} {} over the {}'.format(bar3, bar2, bar1)
# The lazy dog jumped over the foobar

JavaScript 有这样的函数吗?如果没有,我将如何创建一个遵循与 Python 实现相同的语法的代码?

45896 次浏览

摘自雅虎图书馆:

YAHOO.Tools.printf = function() {
var num = arguments.length;
var oStr = arguments[0];
for (var i = 1; i < num; i++) {
var pattern = "\\{" + (i-1) + "\\}";
var re = new RegExp(pattern, "g");
oStr = oStr.replace(re, arguments[i]);
}
return oStr;
}

可以这么说:

bar1 = 'foobar'
bar2 = 'jumped'
bar3 = 'dog'


foo = YAHOO.Tools.printf('The lazy {0} {1} over the {2}', bar3, bar2, bar1);

JavaScript 没有这样的函数 AFAIK。

您可以通过修改 String 类的原型对象来添加一个 format ()方法,该方法接受数量可变的参数。

在 format 方法中,您必须获取 String 的实例值(实际的字符串) ,然后将其解析为“{}”并插入适当的参数。

然后将新字符串返回给调用者。

这是我的第一次尝试。请随意指出缺点。

示例: < a href = “ http://jsfiddle.net/wFb2p/5/”rel = “ nofollow”> http://jsfiddle.net/wfb2p/5/

String.prototype.format = function() {
var str = this;
var i = 0;
var len = arguments.length;
var matches = str.match(/{}/g);
if( !matches || matches.length !== len ) {
throw "wrong number of arguments";
}
while( i < len ) {
str = str.replace(/{}/, arguments[i] );
i++;
}
return str;
};

编辑: 通过消除 while语句中的 .match()调用,使其更加高效。

编辑: 更改它,如果没有传递任何参数,将抛出相同的错误。

默认情况下,JavaScript 没有字符串格式化函数,但是您可以创建自己的函数或使用其他人创建的函数(例如 Sprintf)

另一种方法,使用 String.prototype.replace方法,将“替换”函数作为第二个参数:

String.prototype.format = function () {
var i = 0, args = arguments;
return this.replace(/{}/g, function () {
return typeof args[i] != 'undefined' ? args[i++] : '';
});
};


var bar1 = 'foobar',
bar2 = 'jumped',
bar3 = 'dog';


'The lazy {} {} over the {}'.format(bar3, bar2, bar1);
// "The lazy dog jumped over the foobar"

在寻找同一个问题的答案时,我发现了这个: https://github.com/davidchambers/string-format,它是“受 Python 的 str.format()启发而设计的 JavaScript 字符串格式”。它似乎与 python 的 format()函数非常相似。

此代码允许您确切地指定用哪些字符串替换哪些括号。方括号不需要与参数的顺序相同,并且可以使用多个方括号。Format 函数采用一个值数组作为参数,每个键都是括号中的“变量”之一,并由相应的值替换。

String.prototype.format = function (arguments) {
var this_string = '';
for (var char_pos = 0; char_pos < this.length; char_pos++) {
this_string = this_string + this[char_pos];
}


for (var key in arguments) {
var string_key = '{' + key + '}'
this_string = this_string.replace(new RegExp(string_key, 'g'), arguments[key]);
}
return this_string;
};


'The time is {time} and today is {day}, {day}, {day}. Oh, and did I mention that the time is {time}.'.format({day:'Monday',time:'2:13'});
//'The time is 2:13 and today is Monday, Monday, Monday. Oh, and did I mention that the time is 2:13.'

约翰逊:

String.prototype.format = function () {
var str = this;
for (var i = 0; i < arguments.length; i++) {
str = str.replace('{' + i + '}', arguments[i]);
}
return str;
}


bar1 = 'foobar';
bar2 = 'jumped';
bar3 = 'dog';


python_format = 'The lazy {2} {1} over the {0}'.format(bar1,bar2,bar3);


document.getElementById("demo").innerHTML = "JavaScript equivalent of Python's format() function:<br><span id='python_str'>" + python_format + "</span>";

HTML:

<p id="demo"></p>

CSS:

span#python_str {
color: red;
font-style: italic;
}

产出:

相当于 Python 的 format ()函数的 JavaScript:

那条懒狗跳过了食物栏

演示:

JsFiddle

在文件里

Https://github.com/brucesherwood/glowscript/blob/master/lib/glow/api_misc.js

是一个函数 String.Prototype.format = function (args) ,它完全实现了 Python string.format ()函数,而不仅限于处理字符串。

有一种方法,但不完全使用格式。

var name = "John";
var age = 19;
var message = `My name is ${name} and I am ${age} years old`;
console.log(message);

Jsfiddle-链接

博士

foo = (a, b, c) => `The lazy ${a} ${b} over the ${c}`

为什么仅仅模板字符串是不够的

ES6模板字符串提供了一个与 Python 字符串格式非常相似的特性。但是,在构造字符串之前必须了解变量:

var templateString = `The lazy ${bar3} ${bar2} over the ${bar1}`;

为什么要格式化?

Python 的 str.format允许您指定字符串 之前,您甚至知道要将哪些值插入其中,比如:

foo = 'The lazy {} {} over the {}'


bar1 = 'foobar'
bar2 = 'jumped'
bar3 = 'dog'


foo.format(bar3, bar2, bar1)

解决方案

使用 箭头函数,我们可以优雅地包装模板字符串,以供以后使用:

foo = (a, b, c) => `The lazy ${a} ${b} over the ${c}`


bar1 = 'foobar';
bar2 = 'jumped';
bar3 = 'dog';


foo(bar3, bar2, bar1)

当然,这也适用于常规函数,但是 Arrow 函数允许我们将其作为一行程序。这两个特性在大多数浏览器和运行时都可用:

对于那些寻找简单 ES6解决方案的人来说。

首先,我提供了一个函数,而不是扩展原生 String 原型,因为通常不鼓励这样做。

// format function using replace() and recursion


const format = (str, arr) => arr.length > 1
? format(str.replace('{}', arr[0]), arr.slice(1))
: (arr[0] && str.replace('{}', arr[0])) || str


// Example usage


const str1 = 'The {} brown {} jumps over the {} dog'


const formattedString = formatFn(str1, ['quick','fox','lazy'])


console.log(formattedString)

乌桑多分裂:

String.prototype.format = function (args) {
var text = this
for(var attr in args){
text = text.split('${' + attr + '}').join(args[attr]);
}
return text
};


json = {'who':'Gendry', 'what':'will sit', 'where':'in the Iron Throne'}
text = 'GOT: ${who} ${what} ${where}';


console.log('context: ',json);
console.log('template: ',text);
console.log('formated: ',text.format(json));

Usando Regex:

String.prototype.format = function (args) {
var text = this
for(var attr in args){
var rgx = new RegExp('\\${' + attr + '}','g');
text = text.replace(rgx, args[attr]);
}
return text
};


json = {'who':'Gendry', 'what':'will sit', 'where':'in the Iron Throne'}
text = 'GOT: ${who} ${what} ${where}';


console.log('context: ',json);
console.log('template: ',text);
console.log('formated: ',text.format(json));

String.prototype.format = function () {
var i=0,args=arguments,formats={
"f":(v,s,c,f)=>{s=s||' ',c=parseInt(c||'0'),f=parseInt(f||'-1');v=f>0?Math.floor(v).toString()+"."+Math.ceil(v*Math.pow(10,f)).toString().slice(-f):(f==-1?v.toString():Math.floor(v).toString());return c>v.length?s.repeat(c-v.length)+v:v;},
"d":(v,s,c,f)=>{s=s||' ',c=parseInt(c||'0');v=Math.floor(v).toString();return c>v.length?s.repeat(c-v.length)+v:v;},
"s":(v,s,c,f)=>{s=s||' ',c=parseInt(c||'0');return c>v.length?s.repeat(c-v.length)+v:v;},
"x":(v,s,c,f)=>{s=s||' ',c=parseInt(c||'0');v=Math.floor(v).toString(16);return c>v.length?s.repeat(c-v.length)+v:v;},
"X":(v,s,c,f)=>{s=s||' ',c=parseInt(c||'0');v=Math.floor(v).toString(16).toUpperCase();return c>v.length?s.repeat(c-v.length)+v:v;},
};
return this.replace(/{(\d+)?:?([0=-_*])?(\d+)?\.?(\d+)?([dfsxX])}/g, function () {
let pos = arguments[1]||i;i++;
return typeof args[pos] != 'undefined' ? formats[arguments[5]](args[pos],arguments[2],arguments[3],arguments[4]) : '';
});
};

可以在 JS 中使用模板文本,

const bar1 = 'foobar'
const bar2 = 'jumped'
const bar3 = 'dog'
foo = `The lazy ${bar3} ${bar2} over the ${bar1}`

我觉得这很有帮助。

如果您(像我一样)只需要 python 格式函数的有限子集来进行简单的字符串替换,并且性能不是关键的,那么一个非常简单的29行纯 Javascript 函数就足够了。

Javascript 调用: format(str, data)

类似的 Python 调用: str.format(**data),告诫这个 javascript 函数与 Python 不同,如果字符串包含在提供的数据中没有找到的 varname,则不会抛出错误。

/*
* format(str, data): analogous to Python's str.format(**data)
*
* Example:
*   let data = {
*     user: {
*       name: { first: 'Jane', last: 'Doe' }
*     },
*     email: 'jane@doe.com',
*     groups: ["one","two"]
*   };
*
*   let str = 'Hi {user.name.first} {user.name.last}, your email address is {email}, and your second group is {groups[1]}'
*
*   format(str, data)
*   => returns "Hi Jane Doe, your email address is jane@doe.com, and your second group is two"
*/


function format(str, data) {
var varnames = {};
function array_path(path, i) {
var this_k = '[' + i + ']';
if (!path.length)
return [this_k];
path = path.slice();
path[path.length - 1] += this_k;
return path;
}
function add_varnames(this_data, path) {
if (this_data.constructor == Array) {
for (var i = 0; i < this_data.length; i++)
add_varnames(this_data[i], array_path(path, i));
}
else if (this_data.constructor == Object) {
for (var k in this_data)
add_varnames(this_data[k], path.concat(k));
}
else {
var varname = '{' + path.join('.') + '}';
varnames[varname] = String(this_data);
}
}
add_varnames(data, []);
for (var varname in varnames)
str = str.replace(varname, varnames[varname]);
return str;
}

帕特里克 · 阿克斯特兰报道了我自己的简化版 雅虎的 printf:

function format() {
return [...arguments].reduce((acc, arg, idx) =>
acc.replace(new RegExp("\\{" + (idx - 1) + "\\}", "g"), arg));
}


console.log(
format('Confirm {1} want {0} beers', 3, 'you')
);

不使用额外函数的简单实现

[bar1, bar2, bar3].reduce(
(str, val) => str.replace(/{}/, val),
'The lazy {} {} over the {}'
)
String.prototype.format = function(args){
//args - hash of params
var text = this
for(var attr in args){
text = text.split('${' + attr + '}').join(args[attr]);
}
return text
}

用法: ‘ Hello,${ NAME }。这是 ${ formAT }’. FORMAT ({ NAME: ‘ guys’,FORMAT AT: ‘ FORMAT ()’})