Question JavaScript équivalent à printf / String.Format


Je cherche un bon équivalent JavaScript du C / PHP printf() ou pour les programmeurs C # / Java, String.Format() (IFormatProvider pour .NET).

Mon exigence de base est un format de séparateur de milliers pour les nombres pour l'instant, mais quelque chose qui gère beaucoup de combinaisons (y compris les dates) serait bon.

Je réalise que Microsoft Ajax bibliothèque fournit une version de String.Format(), mais nous ne voulons pas les frais généraux de ce cadre.


1605
2018-01-12 20:02


origine


Réponses:


Essayer sprintf () pour JavaScript.


Mettre à jourOk, si vous voulez vraiment faire une méthode de formatage simple, ne faites pas les remplacements successivement mais faites-les simultanément.

Parce que la plupart des autres propositions mentionnées échouent lorsqu'une chaîne de remplacement du remplacement précédent contient également une séquence de format comme ceci:

"{0}{1}".format("{1}", "{0}")

Normalement, vous vous attendez à ce que la sortie soit {1}{0} mais la sortie réelle est {1}{1}. Faites donc un remplacement simultané au lieu de suggestion de fearphage.


684



En s'appuyant sur les solutions suggérées précédemment:

// First, checks if it isn't implemented yet.
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}

"{0} is dead, but {1} is alive! {0} {2}".format("ASP", "ASP.NET")

les sorties

ASP est mort, mais ASP.NET est vivant! ASP {2}


Si vous préférez ne pas modifier StringLe prototype:

if (!String.format) {
  String.format = function(format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number] 
        : match
      ;
    });
  };
}

Vous donne le plus familier:

String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');

avec le même résultat:

ASP est mort, mais ASP.NET est vivant! ASP {2}


1278



C'est drôle parce que Stack Overflow a sa propre fonction de formatage pour le String prototype appelé formatUnicorn. Essayez-le! Allez dans la console et tapez quelque chose comme:

"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});

Firebug

Vous obtenez cette sortie:

Hello, Gabriel, are you feeling OK?

Vous pouvez utiliser des objets, des tableaux et des chaînes comme arguments! J'ai eu son code et l'ai retravaillé pour produire une nouvelle version de String.prototype.format:

String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
function () {
    "use strict";
    var str = this.toString();
    if (arguments.length) {
        var t = typeof arguments[0];
        var key;
        var args = ("string" === t || "number" === t) ?
            Array.prototype.slice.call(arguments)
            : arguments[0];

        for (key in args) {
            str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
        }
    }

    return str;
};

Notez l'astucieux Array.prototype.slice.call(arguments) appel - cela signifie que si vous lancez des arguments qui sont des chaînes ou des nombres, pas un seul objet de style JSON, vous obtenez des C # String.Format comportement presque exactement.

"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"

C'est parce que Arrayde slice va forcer tout ce qui est dans arguments dans un Array, que ce soit à l'origine ou non, et key sera l'indice (0, 1, 2 ...) de chaque élément du tableau forcé dans une chaîne (par exemple, "0", donc "\\{0\\}" pour votre premier motif regexp).

Soigné.


366



Formatage de nombres en JavaScript

Je suis arrivé à cette page de questions en espérant trouver comment numéros de format en JavaScript, sans introduire encore une autre bibliothèque. Voici ce que j'ai trouvé:

Arrondir les nombres à virgule flottante

L'équivalent de sprintf("%.2f", num) en JavaScript semble être num.toFixed(2), quels formats num avec 2 décimales, avec arrondi (mais voir le commentaire de @ ars265 à propos de Math.round au dessous de).

(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)

Forme exponentielle

L'équivalent de sprintf("%.2e", num) est num.toExponential(2).

(33333).toExponential(2); // "3.33e+4"

Hexadécimal et autres bases

Pour imprimer des nombres dans la base B, essayez num.toString(B). JavaScript prend en charge la conversion automatique vers et à partir des bases 2 à 36 (en outre, certains navigateurs ont support limité pour l'encodage en base64).

(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559

Pages de référence

Tutoriel rapide sur le formatage des numéros JS

Page de référence de Mozilla pour toFixed () (avec des liens vers toPrecision (), toExponential (), toLocaleString (), ...)


288



jsxt, Zippo

Cette option convient mieux.

String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        var regexp = new RegExp('\\{'+i+'\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[i]);
    }
    return formatted;
};

Avec cette option, je peux remplacer des chaînes comme celles-ci:

'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');

Avec votre code, le second {0} ne sera pas remplacé. ;)


168



De ES6 sur vous pourriez utiliser chaînes de modèle:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Sachez que les chaînes de modèles sont entouré de backticks `au lieu de (simples) citations.

Pour plus d'informations:

https://developers.google.com/web/updates/2015/01/ES6-Template-Strings

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

Remarque: Consultez le site mozilla pour trouver la liste des navigateurs pris en charge.


168



J'utilise cette fonction simple:

String.prototype.format = function() {
    var formatted = this;
    for( var arg in arguments ) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

C'est très similaire à string.format:

"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")

90



Voici un minimal implémentation de sprintf en JavaScript: il ne fait que "% s" et "% d", mais j'ai laissé de l'espace pour qu'il soit étendu. C'est inutile pour le PO, mais d'autres personnes qui trébuchent sur ce sujet venant de Google pourraient en bénéficier.

function sprintf() {
    var args = arguments,
    string = args[0],
    i = 1;
    return string.replace(/%((%)|s|d)/g, function (m) {
        // m is the matched format, e.g. %s, %d
        var val = null;
        if (m[2]) {
            val = m[2];
        } else {
            val = args[i];
            // A switch statement so that the formatter can be extended. Default is %s
            switch (m) {
                case '%d':
                    val = parseFloat(val);
                    if (isNaN(val)) {
                        val = 0;
                    }
                    break;
            }
            i++;
        }
        return val;
    });
}

Exemple:

alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0

Contrairement à des solutions similaires dans les réponses précédentes, celui-ci fait toutes les substitutions en une fois, donc il ne remplacera pas les parties de valeurs précédemment remplacées.


48



Pour Node.js les utilisateurs sont là util.format qui a une fonctionnalité semblable à printf:

util.format("%s world", "Hello")

45



Je suis surpris que personne n'a utilisé reduce, c'est une fonction JavaScript native et concise.

ES6 (EcmaScript2015)

String.prototype.format = function() {
  return [...arguments].reduce((p,c) => p.replace(/%s/,c), this);
};

console.log('Is that a %s or a %s?... No, it\'s %s!'.format('plane', 'bird', 'SOman'));

<ES6

function interpolate(theString, argumentArray) {
    var regex = /%s/;
    var _r=function(p,c){return p.replace(regex,c);}
    return argumentArray.reduce(_r, theString);
}

interpolate("%s, %s and %s", ["Me", "myself", "I"]); // "Me, myself and I"

Comment ça marche:

réduire applique une fonction contre un accumulateur et chaque élément du tableau (de gauche à droite) pour le réduire à une seule valeur.

var _r= function(p,c){return p.replace(/%s/,c)};

console.log(
  ["a", "b", "c"].reduce(_r, "[%s], [%s] and [%s]") + '\n',
  [1, 2, 3].reduce(_r, "%s+%s=%s") + '\n',
  ["cool", 1337, "stuff"].reduce(_r, "%s %s %s")
);


36



Les programmeurs JavaScript peuvent utiliser String.prototype.sprintf à https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js. Voici un exemple:

var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
    d.getHours(), 
    d.getMinutes(), 
    d.getSeconds());

30