【问题标题】:JavaScript equivalent of Python's format() function?JavaScript 等效于 Python 的 format() 函数?
【发布时间】:2011-06-25 20:17:02
【问题描述】:

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 实现相同的语法?

【问题讨论】:

  • 查看这个帖子以获得解决方案:stackoverflow.com/questions/610406/…
  • 我总是在我的许多网站中使用 jQuery,所以它不会受到伤害。 JS 是否允许您对字符串对象进行子类化或添加函数?
  • JavaScript 是一种基于原型的语言。您可以通过增强其通用原型来扩展一个类型的所有对象。
  • prototype 是该语言的一个特性。 prototypejs 库是完全独立的。

标签: javascript python format


【解决方案1】:

另一种方法,使用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"

【讨论】:

  • 是的,有道理。 jsfiddle.net/wFb2p/6 我以前没有掌握这个函数在每场比赛中运行一次的事实。 +1
  • 使用替换函数也意味着您可以很容易地扩展它以支持非=空占位符,例如{1}
  • 不鼓励扩展原生类。你应该使用一个函数,或者定义你自己的类/子类。这有助于其他程序员区分原生和非原生特性。它还避免了代码干扰的风险——其他人定义的也可能定义String.Prototype.format
  • 为什么这不是 JavaScript 的标准部分?
  • 我在每个JS项目上都使用这个功能,谢谢!
【解决方案2】:

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

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

jsfiddle - link

【讨论】:

  • 这是如何工作的?我不熟悉 Javascript 中的${...}。不过太棒了!
  • 这一切都很有趣,但这并不能解决问题。如果我们不能将特定的上下文传递给 ES6 中的方法,那么在许多情况下它是毫无意义的。你写的大多只是字符串连接的语法糖。
  • 这确实解决了问题,如果你没有上下文,你可以轻松地做类似var message = `My name is ${name || 'default'} and I am ${age || 'default'} years old`;
  • @shrewmouse:或者在 Python 3.6 中只是 f'My name is {name} and I am {age}'
【解决方案3】:

tl;博士

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

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

ES6 template strings 提供了一个与 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)

解决方案

使用arrow function,我们可以优雅地包装模板字符串以备后用:

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

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

foo(bar3, bar2, bar1)

当然,这也适用于常规函数,但箭头函数允许我们将其设为单行。这两个功能在大多数浏览器和运行时都可用:

【讨论】:

  • 这忽略了使用 xx.format() 的一个主要原因,与@Yash Mehrotra 的答案相同的缺点是,要格式化的字符串可能需要是动态的而不是硬编码的。跨度>
  • 这应该是最佳答案。谢谢!
【解决方案4】:

在寻找相同问题的答案时,我发现了这个:https://github.com/davidchambers/string-format,它是“受 Python 的 str.format() 启发的 JavaScript 字符串格式化”。好像和python的format()函数差不多。

【讨论】:

  • 我在寻找什么。不过暂时不支持 Python 填充功能。
【解决方案5】:

取自雅虎图书馆:

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

【讨论】:

    【解决方案6】:

    这是我的第一次尝试。欢迎指出缺陷。

    示例: 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() 调用使其效率更高。

    编辑:对其进行了更改,如果您不传递任何参数,则会引发相同的错误。

    【讨论】:

    • 哇!那很快。谢谢!
    • 确保检查arguments[i] 存在。
    • @zzzzBov:好点。如果参数的数量与找到的{} 的数量不匹配,我正要提供一个引发错误的更新。编辑:更新。
    【解决方案7】:

    你可以在 JS 中使用模板字面量,

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

    我认为这很有帮助。

    【讨论】:

      【解决方案8】:

      Usando 分裂:

      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 正则表达式:

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

      【讨论】:

      • 方便。我在原型之外实现了这个,并添加了hasOwnProperty 检查:const format = (s, args) =&gt; { for (let attr in args) if (args.hasOwnProperty(attr)) s = s.split('${' + attr + '}').join(args[attr]); return s || ''; };
      【解决方案9】:

      此代码允许您准确指定用哪些字符串替换哪些括号。括号不需要与参数的顺序相同,多个括号是可能的。格式函数将一个值数组作为其参数,每个键都是括号中的“变量”之一,它被其对应的值替换。

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

      【讨论】:

      • 看起来不错,只是代码的第一部分有点毫无意义,因为字符串在技术上是不可变的。您实际上不必连接每个字母。只需this_string = this。应该够了。由于您稍后将使用替换,因此无论如何都不会触及。
      【解决方案10】:

      JS:

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

      输出:

      JavaScript 等价于 Python 的 format() 函数:

      懒狗跳过foobar

      演示:

      jsFiddle

      【讨论】:

        【解决方案11】:
        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]) : '';
            });
        };
        

        【讨论】:

          【解决方案12】:

          JavaScript 没有这样的函数 AFAIK。

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

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

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

          【讨论】:

            【解决方案13】:

            默认情况下,JavaScript 没有字符串格式化功能,但您可以创建自己的或使用其他人制作的(例如 sprintf

            【讨论】:

              【解决方案14】:

              在文件中

              https://github.com/BruceSherwood/glowscript/blob/master/lib/glow/api_misc.js

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

              【讨论】:

              • 不完全。它不支持像 "start {:.{}f} end".format(14, 5) 这样的嵌套表达式
              【解决方案15】:

              适合那些寻找简单 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)

              【讨论】:

                【解决方案16】:

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

                Javascript 调用:format(str, data)

                类似的 python 调用:str.format(**data),但需要注意的是,与 Python 不同的是,如果字符串包含在提供的数据中找不到的 varname,则此 javascript 函数不会引发错误。

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

                【讨论】:

                  【解决方案17】:

                  PatrikAkerstrand 报告的我自己的YAHOO's 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')
                  );

                  【讨论】:

                    【解决方案18】:

                    不使用额外功能的简单实现

                    [bar1, bar2, bar3].reduce(
                      (str, val) => str.replace(/{}/, val),
                      'The lazy {} {} over the {}'
                    )
                    

                    【讨论】:

                      猜你喜欢
                      • 2012-11-18
                      • 2011-06-18
                      • 2015-05-24
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-11-07
                      • 2011-07-09
                      相关资源
                      最近更新 更多