JQuery içinde String.format eşdeğeri


Yanıtlar:


193

ASP.NET AJAX için kaynak kodu kullanılabilir bunu üzerinden almak ve ayrı bir JS dosyasına kullanmaya devam etmek istiyorum parçalar içerebilir, böylece referans için. Veya bunları jQuery'ye bağlayabilirsiniz.

İşte format fonksiyonu ...

String.format = function() {
  var s = arguments[0];
  for (var i = 0; i < arguments.length - 1; i++) {       
    var reg = new RegExp("\\{" + i + "\\}", "gm");             
    s = s.replace(reg, arguments[i + 1]);
  }

  return s;
}

Ve işte bitleri ile ve prototip fonksiyonları ile başlar ...

String.prototype.endsWith = function (suffix) {
  return (this.substr(this.length - suffix.length) === suffix);
}

String.prototype.startsWith = function(prefix) {
  return (this.substr(0, prefix.length) === prefix);
}

2
Çok fazla varmış gibi görünmüyor. JavaScript sürümünde tüm süslü sayı biçimlendirme öğeleri yok. blog.stevex.net/index.php/string-formatting-in-csharp
Nosredna

Vay be, aslında bunu zaten düşündüm ama lisans nedeniyle mümkün olmadığını düşündüm, Microsoft Permissive Lisansı altında bıraktıklarını bilmiyordum, bunun için çok teşekkürler
Waleed Eissa

23
Lisans ya da lisans yok .. Çok basit bir şey yazmanın tek bir doğru yolu var
adamJLev

1
Biçim her çağrıldığında her bir bağımsız değişken için bir RegEx nesnesi oluşturmak (ve ardından atmak) çöp toplayıcısını fazla zorlayabilir.
Mayıs

14
Uyarı: Bu yinelemeli biçimlendirir: Eğer varsa bu yüzden {0}{1}, {0}ilk değiştirilir ve daha sonra tüm olaylar olacak {1}zaten ikame metin ve orijinal biçimi hem değiştirilecektir içinde.
Zenexer

147

Bu, Josh'un yayınladığı işlevin daha hızlı / daha basit (ve prototipik) bir çeşididir:

String.prototype.format = String.prototype.f = function() {
    var s = this,
        i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};

Kullanımı:

'Added {0} by {1} to your collection'.f(title, artist)
'Your balance is {0} USD'.f(77.7) 

Bunu o kadar çok kullanıyorum ki, sadece onu taklit ettim f, ama daha ayrıntılı da kullanabilirsiniz format. Örneğin'Hello {0}!'.format(name)


1
Modern tarayıcılarda daha da basit yaklaşımlar vardır: stackoverflow.com/a/41052964/120296
david

3
@david Şablon dizgisi gerçekten aynı şey DEĞİLDİR. Dize birleştirme için sözdizimsel şekerdir, bu da güzel ancak biçimlendirme ile aynı değildir. Anında çalışırlar, bu nedenle değiştirmeler tanım noktasında olmalıdır. Bu nedenle bunları bir metin dosyasına veya veritabanına depolayamazsınız. Aslında, onları herhangi bir yerde saklamanın tek yolu onları bir işleve koymaktır. Biçimlendirilmiş dize işlevi, değişkenin adını önemsemeyen konumsal değişimler alır.
krowe2

131

Yukarıdaki işlevlerin çoğu (Julian Jelfs hariç) aşağıdaki hatayı içerir:

js> '{0} {0} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 3.14 afoobc foo

Veya bağımsız değişken listesinin sonundan geriye doğru sayan varyantlar için:

js> '{0} {0} {1} {2}'.format(3.14, 'a{0}bc', 'foo');
3.14 3.14 a3.14bc foo

İşte doğru bir işlev. Julian Jelfs kodunun prototip bir varyantı, biraz daha sıkı yaptım:

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{(\d+)\}/g, function (m, n) { return args[n]; });
};

Ve işte biraz daha gelişmiş bir versiyon, parantezleri iki katına çıkararak kaçmanıza izin veriyor:

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
    if (m == "{{") { return "{"; }
    if (m == "}}") { return "}"; }
    return args[n];
  });
};

Bu doğru çalışıyor:

js> '{0} {{0}} {{{0}}} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 {0} {3.14} a{2}bc foo

İşte Blair Mitchelmore'un bir sürü güzel ekstra özelliği ile iyi bir uygulaması: https://web.archive.org/web/20120315214858/http://blairmitchelmore.com/javascript/string.format


Ve başka ben çok yakından bakmadım biri, ama hangi gibi biçimleri uygulamak gibi görünüyor {0: + $ #, 0.00; - $ #, 0.00; 0}: masterdata.dyndns.org/r/string_format_for_javascript
gpvos

Ooh ve Python enterpolasyon formatını kullanan bir
kod

Biçim uygulama ben taşındı iki yorum söz masterdata.se/r/string_format_for_javascript
gpvos

Not: ianj'ın bu sayfadaki başka bir yerde vereceği yanıt, sayısal parametreler yerine adlandırılmış öğeyi kullanmanızı sağlar. Yöntemini prototipleri kullanan bir yöntemle değiştirirseniz, ikinci parametreyi slice.call işlevine 1'den 0'a değiştirmeniz gerekir.
gpvos

48

Bir koleksiyonu veya diziyi bağımsız değişken olarak alan bir biçim işlevi hazırladı

Kullanımı:

format("i can speak {language} since i was {age}",{language:'javascript',age:10});

format("i can speak {0} since i was {1}",'javascript',10});

Kod:

var format = function (str, col) {
    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);

    return str.replace(/\{\{|\}\}|\{(\w+)\}/g, function (m, n) {
        if (m == "{{") { return "{"; }
        if (m == "}}") { return "}"; }
        return col[n];
    });
};

5
Güzel olan, eksik olan tek şey: String.prototype.format = function (col) {dönüş biçimi (this, col);}
Erik

10
string uzatmak değil tercih
ianj

3
kullanımda küçük bir yazım hatası vardır: 2. satır şöyle olmalıdır: format ("{1} olduğu için {0} konuşabilirim", "javascript ', 10);
Guillaume Gendre

Neden dize kullanarak genişletmeyi tercih etmiyorsunuz String.prototype?
Kiquenet

36

Resmi bir seçenek var: jQuery.validator.format .

JQuery Validation Plugin 1.6 (en azından) ile birlikte gelir. .NET'te bulunanlara
oldukça benzer String.Format.

Düzenle Sabit bozuk bağlantı.



13

Q'nun ne istediğini tam olarak bilmese de, benzer olan ancak numaralı yerine adlandırılmış yer tutucular kullanan bir tane oluşturdum. Ben şahsen argümanları adlandırmayı tercih ediyorum ve sadece bir nesneyi argüman olarak gönderiyorum (daha ayrıntılı, ancak bakımı daha kolay).

String.prototype.format = function (args) {
    var newStr = this;
    for (var key in args) {
        newStr = newStr.replace('{' + key + '}', args[key]);
    }
    return newStr;
}

İşte bir örnek kullanım ...

alert("Hello {name}".format({ name: 'World' }));

8

EcmaScript 2015'i (ES6) destekleyen modern bir tarayıcı kullanarak Şablon Dizelerinin keyfini çıkarabilirsiniz . Biçimlendirme yerine, değişken değerini doğrudan buna enjekte edebilirsiniz:

var name = "Waleed";
var message = `Hello ${name}!`;

Şablon dizesinin geri keneler (`) kullanılarak yazılması gerektiğini unutmayın.


6

Şimdiye kadar sunulan yanıtların hiçbirinde, sonraki kullanımlar için bir kez başlatmak ve düzenli ifadeleri saklamak için muhafaza kullanma konusunda belirgin bir optimizasyon yoktur.

// DBJ.ORG string.format function
// usage:   "{0} means 'zero'".format("nula") 
// returns: "nula means 'zero'"
// place holders must be in a range 0-99.
// if no argument given for the placeholder, 
// no replacement will be done, so
// "oops {99}".format("!")
// returns the input
// same placeholders will be all replaced 
// with the same argument :
// "oops {0}{0}".format("!","?")
// returns "oops !!"
//
if ("function" != typeof "".format) 
// add format() if one does not exist already
  String.prototype.format = (function() {
    var rx1 = /\{(\d|\d\d)\}/g, rx2 = /\d+/ ;
    return function() {
        var args = arguments;
        return this.replace(rx1, function($0) {
            var idx = 1 * $0.match(rx2)[0];
            return args[idx] !== undefined ? args[idx] : (args[idx] === "" ? "" : $0);
        });
    }
}());

alert("{0},{0},{{0}}!".format("{X}"));

Ayrıca, örneklerden hiçbiri zaten mevcutsa format () uygulamasına saygı duymaz.


2
rx2 gereksiz, benim uygulama bakın; rx1'de (parantez) var, ancak iç işleve ilettikleri değeri kullanmayın. Ayrıca, bu Javascript motorunda yapmak için bariz bir optimizasyon olduğunu düşünüyorum . Modern tarayıcıların bu optimizasyonu sahne arkasında yapmadığından emin misiniz? Perl bunu 1990'da yaptı. Doğru uygulandığını kontrol etmek için fonksiyonun etrafında bir sarıcı olması haklısın.
gpvos

1
Ayrıca, (args [idx] === "") üzerindeki test benim için gereksiz görünüyor: undefined! == "" nedeniyle zaten bu satırdaki ilk testin kapsamında.
gpvos

4

Benimki burada:

String.format = function(tokenised){
        var args = arguments;
        return tokenised.replace(/{[0-9]}/g, function(matched){
            matched = matched.replace(/[{}]/g, "");
            return args[parseInt(matched)+1];             
        });
    }

Kurşun geçirmez değil, ancak mantıklı bir şekilde kullanırsanız çalışır.


4

Geç sezon geçtikten sonra verilen cevaplara baktım ve benim tuppence değer var:

Kullanımı:

var one = strFormat('"{0}" is not {1}', 'aalert', 'defined');
var two = strFormat('{0} {0} {1} {2}', 3.14, 'a{2}bc', 'foo');

Yöntem:

function strFormat() {
    var args = Array.prototype.slice.call(arguments, 1);
    return arguments[0].replace(/\{(\d+)\}/g, function (match, index) {
        return args[index];
    });
}

Sonuç:

"aalert" is not defined
3.14 3.14 a{2}bc foo

3

Artık Şablon Değişmezlerini kullanabilirsiniz :

var w = "the Word";
var num1 = 2;
var num2 = 3;

var long_multiline_string = `This is very long
multiline templete string. Putting somthing here:
${w}
I can even use expresion interpolation:
Two add three = ${num1 + num2}
or use Tagged template literals
You need to enclose string with the back-tick (\` \`)`;

console.log(long_multiline_string);


3
Yalnızca değişkenlerin yanında dize tanımlandığında çalıştıklarını görene kadar şablon değişmezleri hakkında heyecanlandım. Bana göre bu onları neredeyse işe yaramaz kılıyor; bir nedenden ötürü dizelerimin çoğu, onları dolduran / kullanan koddan ayrı olarak tanımlanır.
taş

2

İşte '{' işaretinden kaçabilen ve atanmamış yer tutucuları temizleyebilen sürümüm.

function getStringFormatPlaceHolderRegEx(placeHolderIndex) {
    return new RegExp('({)?\\{' + placeHolderIndex + '\\}(?!})', 'gm')
}

function cleanStringFormatResult(txt) {
    if (txt == null) return "";

    return txt.replace(getStringFormatPlaceHolderRegEx("\\d+"), "");
}

String.prototype.format = function () {
    var txt = this.toString();
    for (var i = 0; i < arguments.length; i++) {
        var exp = getStringFormatPlaceHolderRegEx(i);
        txt = txt.replace(exp, (arguments[i] == null ? "" : arguments[i]));
    }
    return cleanStringFormatResult(txt);
}
String.format = function () {
    var s = arguments[0];
    if (s == null) return "";

    for (var i = 0; i < arguments.length - 1; i++) {
        var reg = getStringFormatPlaceHolderRegEx(i);
        s = s.replace(reg, (arguments[i + 1] == null ? "" : arguments[i + 1]));
    }
    return cleanStringFormatResult(s);
}

2

Aşağıdaki cevap muhtemelen en verimli olanıdır, ancak yalnızca 1 ila 1 argüman eşlemesi için uygun olma uyarısına sahiptir. Bu, dizeleri birleştirmenin en hızlı yolunu kullanır (bir stringbuilder'a benzer: birleştirilmiş dizeler dizisi). Bu benim kendi kodum. Muhtemelen daha iyi bir ayırıcıya ihtiyaç duyar.

String.format = function(str, args)
{
    var t = str.split('~');
    var sb = [t[0]];
    for(var i = 0; i < args.length; i++){
        sb.push(args[i]);
        sb.push(t[i+1]);
    }
    return sb.join("");
}

Gibi kullanın:

alert(String.format("<a href='~'>~</a>", ["one", "two"]));

2
Kabul edilen cevap en iyi cevaptır. Mümkün olan her verimliliği (uzun döngüler) sıkıştırmak istediğiniz senaryolarda yararlı olan benzersiz bir cevap veriyorum ve 1: 1 argüman eşlemeniz var. Daha verimli cuz replace () ve yeni Regex () ile birlikte regex gerçekleştirildiğinde kesinlikle tek split () 'den daha fazla CPU çevrimi kullanılır.
Skychan

-1'e gerek yok. Hayır, yaygın olarak uygulanamaz, ancak doğrudur, bu biraz daha verimli olacaktır. Şimdi, yazar için, bir mimari soru: bu tür bir optimizasyonun gerekli olacağı müşteri üzerinde böyle büyük bir veri seti ile ne tür bir uygulama ele alınacak?
Michael Blackburn

İyi nokta Michael Blackburn. Çoğu durum muhtemelen iyidir. Benim durumumda iyi bir veri parçasıyla uğraşıyordum (bir ürün grubundaki ürün varyasyonları, muhtemelen yüzlerce varyant) ve bence kullanıcılar genellikle çok sayıda tarayıcı sekmesi açtığından ve her web sitesi çok fazla CPU emmeye meyilli olduğu için Yüksek verimliliği korumak için bu uygulamayı tercih ettim.
Skychan

2

Bu KURU ilkesini ihlal eder, ancak kısa bir çözümdür:

var button = '<a href="{link}" class="btn">{text}</a>';
button = button.replace('{text}','Authorize on GitHub').replace('{link}', authorizeUrl);

0
<html>
<body>
<script type="text/javascript">
   var str="http://xyz.html?ID={0}&TId={1}&STId={2}&RId={3},14,480,3,38";
   document.write(FormatString(str));
   function FormatString(str) {
      var args = str.split(',');
      for (var i = 0; i < args.length; i++) {
         var reg = new RegExp("\\{" + i + "\\}", "");             
         args[0]=args[0].replace(reg, args [i+1]);
      }
      return args[0];
   }
</script>
</body>
</html>

Bu, URI'ler için iyidir, ancak genel kullanım için, bir dizenin hem biçimi hem de bileşenlerini içermesi çok kırılgandır. Dizeniz virgül içeriyorsa ne olur?
Michael Blackburn

0

Josh Stodola'nın çalışmasına cevap bulamadım, ancak aşağıdakiler benim için çalıştı. Teknik özelliklerine dikkat edin prototype. (IE, FF, Chrome ve Safari'de test edildi.):

String.prototype.format = function() {
    var s = this;
    if(t.length - 1 != args.length){
        alert("String.format(): Incorrect number of arguments");
    }
    for (var i = 0; i < arguments.length; i++) {       
        var reg = new RegExp("\\{" + i + "\\}", "gm");
        s = s.replace(reg, arguments[i]);
    }
    return s;
}

sGerçekten olmalıdır klon arasında thisyıkıcı bir yöntem etmemek için, ama gerçekten gerekli değildir.


Bu yıkıcı bir yöntem değil. S, s.replace () dönüş değeriyle yeniden atandığında, bu dokunulmamış olarak kalır.
gpvos

0

Yukarıdaki adamJLev'in harika cevabına genişleyen TypeScript versiyonu:

// Extending String prototype
interface String {
    format(...params: any[]): string;
}

// Variable number of params, mimicking C# params keyword
// params type is set to any so consumer can pass number
// or string, might be a better way to constraint types to
// string and number only using generic?
String.prototype.format = function (...params: any[]) {
    var s = this,
        i = params.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), params[i]);
    }

    return s;
};

0

Ben dize prototip ekler bir dalgıç var: string.format Sadece diğer örneklerin bazıları kadar kısa değil, ama çok daha esnek.

Kullanım c # sürümüne benzer:

var str2 = "Meet you on {0}, ask for {1}";
var result2 = str2.format("Friday", "Suzy"); 
//result: Meet you on Friday, ask for Suzy
//NB: also accepts an array

Ayrıca, ad ve nesne özelliklerini kullanma desteği eklendi

var str1 = "Meet you on {day}, ask for {Person}";
var result1 = str1.format({day: "Thursday", person: "Frank"}); 
//result: Meet you on Thursday, ask for Frank

0

Diziyi bunun gibi değiştirmelerle de kapatabilirsiniz.

var url = '/getElement/_/_/_'.replace(/_/g, (_ => this.ar[this.i++]).bind({ar: ["invoice", "id", 1337],i: 0}))
> '/getElement/invoice/id/1337

ya da deneyebilirsin bind

'/getElement/_/_/_'.replace(/_/g, (function(_) {return this.ar[this.i++];}).bind({ar: ["invoice", "id", 1337],i: 0}))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.