2416 votes

équivalent JavaScript de printf/String.Format

Je suis à la recherche d'un bon équivalent JavaScript de la C/PHP printf() ou pour les programmeurs C#/Java, String.Format() ( IFormatProvider pour .NET).

Pour l'instant, je n'ai besoin que d'un format de séparateur de milliers pour les nombres, mais quelque chose qui gère de nombreuses combinaisons (y compris les dates) serait bien.

Je réalise que Microsoft Ajax fournit une version de String.Format() mais nous ne voulons pas de l'ensemble des frais généraux de ce cadre.

4 votes

En dehors de toutes les bonnes réponses ci-dessous, vous voudrez peut-être jeter un coup d'œil à celle-ci : stackoverflow.com/a/2648463/1712065 ce qui, selon moi, est la solution la plus efficace à ce problème.

3 votes

J'ai écrit un bon marché qui utilise la syntaxe printf de type C.

0 votes

Var search = [$scope.dog, "1"] ; var url = vsprintf(" terre/Services/dogSearch.svc/FindMe/%s/%s ", search) ; ***Pour node, vous pouvez obtenir votre module par "npm install sprintf-js".

1619voto

Gumbo Points 279147

JavaScript actuel

À partir de ES6, vous pouvez utiliser des chaînes de modèles :

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

Voir l'article de Kim responder ci-dessous pour plus de détails.


Réponse plus ancienne

Essayez sprintf() pour JavaScript .


Si vous voulez vraiment faire une méthode de formatage simple par vous-même, 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 celle-ci :

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

Normalement, vous devriez vous attendre à ce que la sortie soit {1}{0} mais la sortie réelle est {1}{1} . Faites donc un remplacement simultané à la place comme dans suggestion de fearphage .

29 votes

Si l'on ne souhaite qu'une simple conversion de chiffres en chaînes de caractères, num.toFixed() pourrait suffire !

2 votes

@MaksymilianMajer cela semble être quelque chose de très différent.

0 votes

@EvanCarroll vous avez raison. Au moment où j'ai écrit ce commentaire, le référentiel de sprintf() for JavaScript n'était pas disponible. underscore.string a plus de fonctionnalités à part sprintf qui est basé sur sprintf() for JavaScript mise en œuvre. En dehors de cela, la bibliothèque est un projet entièrement différent.

1501voto

fearphage Points 7213

En s'appuyant sur les solutions proposé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")

sorties

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


Si vous préférez ne pas modifier String Le prototype de l'entreprise :

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

Cela vous donne une image beaucoup plus familière :

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}

14 votes

L'astuce du || ne fonctionne pas si args[number] est 0. Il faut faire un if() explicite pour voir si (args[number] === undefined).

4 votes

Dans l'instruction else du if raccourci, pourquoi ne pas simplement faire "match" au lieu de "'{' + nombre + '}'". match devrait être égal à cette chaîne.

4 votes

Si vous avez plusieurs chaînes de caractères accolées les unes aux autres (avec l'attribut + -), veillez à mettre la chaîne complète entre parenthèses : ("asd {0}"+"fas {1}").format("first", "second"); Sinon, la fonction ne sera appliquée qu'à la dernière chaîne qui a été ajoutée.

646voto

Gabriel Nahmias Points 237

C'est drôle parce que Stack Overflow a sa propre fonction de mise en forme pour le champ 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 ce résultat :

Hello, Gabriel, are you feeling OK?

Vous pouvez utiliser des objets, des tableaux et des chaînes de caractères comme arguments ! J'ai récupéré 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'astuce Array.prototype.slice.call(arguments) ce qui signifie que si vous introduisez des arguments qui sont des chaînes de caractères ou des nombres, et non pas un objet unique de style JSON, vous obtenez l'appel C# String.Format comportement presque exactement.

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

C'est parce que Array 's slice va forcer ce qui est dans arguments dans un Array que ce soit à l'origine ou non, et la key sera l'index (0, 1, 2...) de chaque élément du tableau converti en chaîne de caractères (par exemple, "0", donc "\\{0\\}" pour votre premier motif regexp).

Neat.

539 votes

C'est plutôt cool de répondre à une question sur stackoverflow avec du code de stackoverflow, +1

1 votes

Quelqu'un comprend-il pourquoi ils utilisent une expression rationnelle pour le remplacement au lieu d'une simple chaîne de caractères ?

7 votes

@JamesManning La regex autorise le drapeau global ( g ), qui peut remplacer la même clé plus d'une fois. Dans l'exemple ci-dessus, vous pourriez utiliser {name} plusieurs fois dans la même phrase et les faire remplacer.

358voto

rescdsk Points 4136

Formatage des nombres en JavaScript

Je suis arrivé sur cette page de questions en espérant trouver comment format des numéros en JavaScript, sans introduire 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) qui présente les formats suivants num à 2 décimales près, avec arrondi (mais voir le commentaire de @ars265 sur les Math.round ci-dessous).

(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) es num.toExponential(2) .

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

Hexadécimal et autres bases

Pour imprimer des nombres en base B, essayez num.toString(B) . JavaScript prend en charge la conversion automatique de et vers les bases 2 à 36 (en outre, certains navigateurs ont support limité pour l'encodage 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 nombres en JS

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

23 votes

Ne serait-il pas préférable de mettre le nombre littéral entre parenthèses, au lieu de laisser un espace blanc bizarre à cet endroit ?

7 votes

Ça aurait probablement l'air mieux, c'est vrai. Mais mon but ici est juste de signaler le piège de l'erreur de syntaxe.

4 votes

Si vous utilisez un navigateur plus ancien ou si vous prenez en charge des navigateurs plus anciens, sachez que certains navigateurs n'ont pas implémenté toFixed de manière correcte. L'utilisation de Math.round à la place de toFixed est une meilleure solution.

182voto

Filipiz Points 915

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 de caractères comme celles-ci :

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

Avec votre code, le deuxième {0} ne serait pas remplacé. ;)

3 votes

gist.github.com/1049426 J'ai mis à jour votre exemple avec cette approche. De nombreux avantages, dont la sauvegarde de l'implémentation native si elle existe, la stringification, etc. J'ai essayé de supprimer les expressions régulières, mais elles sont nécessaires pour le remplacement global :-/.

7 votes

Jsxt est malheureusement sous licence GPL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X