Well , in python or java or ... we do sth like : (the python version )
tmp = "how%s" %("isit")
and now tmp looks like "howisit".
is there any bulit in thing like that in javascript ? ( rather than sprintf )
Thanks
Not build in, but you can make your own templating by extending the String prototype:
String.prototype.template = String.prototype.template ||
function(){
var args = arguments;
function replacer(a){
return args[Number(a.slice(1))-1] || a;
}
return this.replace(/(\$)?\d+/gm,replacer)
};
// usages
'How$1'.template('isit'); //=> Howisit
var greet = new Date('2012/08/08 08:00') < new Date
? ['where','yesterday'] : ['are','today'];
'How $1 you $2?'.template(greet[0],greet[1]); // How where you yesterday?
Nop, there isn't. You can do string concatenation.
var tmp = 'how' + 'isit';
Or replace in other situations. This is a stupid example but you get the idea:
var tmp = 'how{0}'.replace('{0}', 'isit');
No, there is no string formating built in to javascript.
No builtin function is there, however you can very easily build one yourself. The replace function can take a function argument and is the perfect solution for this work. Although be careful with large strings and complicated expressions as this might get slow quickly.
var formatString = function(str) {
// get all the arguments after the first
var replaceWith = Array.prototype.slice.call(arguments, 1);
// simple replacer based on String, Number
str.replace(/%\w/g, function() {
return replaceWith.shift();
});
};
var newString = formatString("how %s %s?", "is", "it");
I think you can use these (simplistic) snippets;
function formatString(s, v) {
var s = (''+ s), ms = s.match(/(%s)/g), m, i = 0;
if (!ms) return s;
while(m = ms.shift()) {
s = s.replace(/(%s)/, v[i]);
i++;
}
return s;
}
var s = formatString("How%s", ["isit"]);
Or;
String.prototype.format = function() {
var s = (""+ this), ms = s.match(/(%s)/g) || [], m, v = arguments, i = 0;
while(m = ms.shift()) {
s = s.replace(/(%s)/, v[i++]);
}
return s;
}
var s = "id:%s, name:%s".format(1,"Kerem");
console.log(s);
Related
I am trying to make something like
var stringUrlTemplate = home.url + '/data/[param1]/[param2]/' + endurl;
And than something like in some loop:
outputUrlItem = print(stringUrlTemplate, someVarialbe, someVariable);
Basically what C/C++ can do.
I cannot use "/data/${param1}/${param2}/" because a string is served by server separetly from JavaScript.
You can use placeholder which can be replaced. Here is an example
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;
});
};
}
var stringUrlTemplate = '/data/{0}/{1}/';
console.log(stringUrlTemplate.format('data1', 'data2'))
OR,
function printf() {
var args = Array.prototype.slice.call(arguments, 1);
var str = arguments[0];
return str.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined' ?
args[number] :
match;
});
};
var stringUrlTemplate = '/data/{0}/{1}/';
console.log(printf(stringUrlTemplate, 'data1', 'data2'))
This package allow reusable template literals - reuse-template-tag, maybe it can help, Here is example from their docs:
const reuseTemplateTag = require('reuse-template-tag')
const template = reuseTemplateTag`
- Hey ${1} How are You?
- Are You ok ${1} ?
- Yes, thanks ${'me'}!
`
console.log(
template({
1: 'Joe',
me: 'Andy'
})
)
// Or provide sequence of values with Array
console.log(
template(['Joe', 'Molly', 'Susan'])
)
Is there a way using JavaScript's RegEx engine to convert
"2" -> "HelloHello"?
"3" -> "HelloHelloHello" ?
"Hello".repeat(2);
This is new! Not available in some browsers!!!! https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
It is perfect if you're working an environment that supports it, like a server-side JS framework.
Here is a way I just came up with, but I admit it is very clumsy.
Array(2 + 1).join("Hello-").split("-").join('');
see comment :P
You can replace the word starting with a upper case letter with itself 2 times like
"HelloHello".replace(/([A-Z][^A-Z]*)/, '$1$1')
String.prototype.replace() allows for a function to be passed to do the replacement, which you can use like:
var a = '123',
words = ['foo', 'bar', 'baz'];
a = a.replace(/\d/g, function (match, i){
return words[i].repeat(match);
});
Which gives:
foobarbarbazbazbaz
http://jsfiddle.net/eqz2y58h/1/
Or (more explicit):
var a = '123',
words = ['foo', 'bar', 'baz'];
a.match(/\d/g).forEach(function (b, c){
a = a.replace(new RegExp(b, 'g'), words[c].repeat(b));
});
Gives:
foobarbarbazbazbaz
http://jsfiddle.net/eqz2y58h/
Here's a function:
function repeatWord(str, n) {
return str + Array(n + 1).join(str.match(/(.*)\1/)[1]);
}
You can use it like:
repeatWord('HelloHello', 3);
'HelloHelloHelloHelloHello'
The 3 means to add Hello to the end 3 more times.
In ES6 Harmony, there is a repeat function. You can add this:
String.prototype.repeat||String.prototype.repeat = a => {
var b = '', _i = 0;
for (; _i < +a; _i += 1) b += this;
return b;
};
You can use it like:
"Hello".repeat(3);
"HelloHelloHello"
Also this might be what you want:
function repeat (format, n) {
return Array(+n + 1).join(format);
}
repeat('Hello', '3');
'HelloHelloHello'
Hi all I'm learning Javascript with the Stoyan Stefanov's book. I'm stuck on Chapter 4 Exercise 4:
Imagine the String()constructor didn't exist. Create a constructor
function MyString()that acts like String()as closely as possible.
You're not allowed to use any built-in string methods or properties,
and remember that String()doesn't exist. You can use this code to
test your constructor:
>>> var s = new MyString('hello');
>>> s[0];
"h"
I can't think on a way to achieve "s[0]", at least not with the knowledge I have now.
Any thoughts?
Thanks
Objects can have properties of themselves defined using array like syntax. String chars can be accessed with array like syntax.
function MyString (str) {
this.length = 0; // string length
var i = 0;
while(str[i] != undefined) {
this.length++;
i++;
}
for (var i=0; i< this.length;i++)
{
this[i]=str[i];
}
}
var s=new MyString('hello');
alert(s[0]); //h
here is my solution for this exercice :
function MyString(msg){
var array_msg = msg.split("");
array_msg.toString = function(){
return array_msg.join("");
};
array_msg.valueOf = function(){
return array_msg.toString();
};
array_msg.charAt = function(i){
if(array_msg[i] === undefined){
return array_msg[0];
}else{return array_msg[i];}
};
array_msg.concat = function(msg2){
return array_msg.join("")+" "+msg2;
};
array_msg.slice = function(d,f){
var res = "";
if(f<0){
f = array_msg.length + f;
}
for(var i=d; i<f; i++){
res += array_msg[i]
}
return res;
};
array_msg.split = function(el){
return array_msg.toString().split(el);
};
return array_msg;
}
A slight variation of the above...more of a tweak than anything
var MyString = function (s) {
for (var i = 0; i < s.length; i++){
this[i] = s[i]
}
this.length = function() .....
You also don't need to assign it to anything as extra as the comment suggests. this[i] will be created for the length of the string passed to s
EDIT:
Part of the question in the book says not to use existing string methods so can't use charAt so I've switched it to s[I]
This is another variation of one of the above solutions but instead of using a for loop I am using a while loop. I don't usually use while loops for these kinds of things but it worked really well here.
Adding the length property is optional.
function MyString(str) {
this.length = 0; // Creating an optional length property
this.value = str;
var i = 0;
while(str[i] != undefined) {
this[i] = str[i];
this.length++;
i++;
}
}
var name = new MyString('billy');
console.log(name.value); // 'billy'
console.log(name[0]); // 'b'
console.log(name.length); // 5
Here's a thing i've been trying to resolve...
We've got some data from an ajax call and the result data is between other stuff a huge string with key:value data. For example:
"2R=OK|2M=2 row(s) found|V1=1,2|"
Is it posible for js to do something like:
var value = someFunction(str, param);
so if i search for "V1" parameter it will return "1,2"
I got this running on Sql server no sweat, but i'm struggling with js to parse the string.
So far i'm able to do this by a VERY rudimentary for loop like this:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
var arr = str.split("|");
var i = 0;
var value = "";
for(i = 0; i<arr.length; ++i){
if( arr[i].indexOf(param)>-1 ){
value = arr[i].split("=")[1];
}
}
console.log(value);
if i put that into a function it works, but i wonder if there's a more efficient way to do it, maybe some regex? but i suck at it. Hopefully somebody may shine a light on this for me?
Thanks!
This seems to work for your specific use-case:
function getValueByKey(haystack, needle) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp(needle + '=(.+)');
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1');
console.log(test);
JS Fiddle demo.
And, to include the separator in your search (in order to prevent somethingElseV1 matching for V1):
function getValueByKey(haystack, needle, separator) {
if (!haystack || !needle) {
return false;
}
else {
var re = new RegExp('\\' + separator + needle + '=(.+)\\' + separator);
return haystack.match(re)[1];
}
}
var str = "2R=OK|2M=2 row(s) found|V1=1,2|",
test = getValueByKey(str, 'V1', '|');
console.log(test);
JS Fiddle demo.
Note that this approach does require the use of the new RegExp() constructor (rather than creating a regex-literal using /.../) in order to pass variables into the regular expression.
Similarly, because we're using a string to create the regular expression within the constructor, we need to double-escape characters that require escaping (escaping first within the string and then escaping within in the created RegExp).
References:
RegExp.
String.match().
This should work for you and it's delimiters are configurable (if you wish to parse a similar string with different delimiters, you can just pass in the delimiters as arguments):
var parseKeyValue = (function(){
return function(str, search, keyDelim, valueDelim){
keyDelim = quote(keyDelim || '|');
valueDelim = quote(valueDelim || '=');
var regexp = new RegExp('(?:^|' + keyDelim + ')' + quote(search) + valueDelim + '(.*?)(?:' + keyDelim + '|$)');
var result = regexp.exec(str);
if(result && result.length > 1)
return result[1];
};
function quote(str){
return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
}
})();
Quote function borrowed form this answer
Usage examples:
var str = "2R=OK|2M=2 row(s) found|V1=1,2|";
var param = "V1";
parseKeyValue(str, param); // "1,2"
var str = "2R=OK&2M=2 row(s) found&V1=1,2";
var param = "2R";
parseKeyValue(str, param, '&'); // "OK"
var str =
"2R=>OK\n\
2M->2 row(s) found\n\
V1->1,2";
var param = "2M";
parseKeyValue(str, param, '\n', '->'); // "2 row(s) found"
Here is another approach:
HTML:
<div id="2R"></div>
<div id="2M"></div>
<div id="V1"></div>
Javascript:
function createDictionary(input) {
var splittedInput = input.split(/[=|]/),
kvpCount = Math.floor(splittedInput.length / 2),
i, key, value,
dictionary = {};
for (i = 0; i < kvpCount; i += 1) {
key = splittedInput[i * 2];
value = splittedInput[i * 2 + 1];
dictionary[key] = value;
}
return dictionary;
}
var input = "2R=OK|2M=2 row(s) found|V1=1,2|",
dictionary = createDictionary(input),
div2R = document.getElementById("2R"),
div2M = document.getElementById("2M"),
divV1 = document.getElementById("V1");
div2R.innerHTML = dictionary["2R"];
div2M.innerHTML = dictionary["2M"];
divV1.innerHTML = dictionary["V1"];
Result:
OK
2 row(s) found
1,2
the list looks like:
3434,346,1,6,46
How can I append a number to it with javascript, but only if it doesn't already exist in it?
Assuming your initial value is a string (you didn't say).
var listOfNumbers = '3434,346,1,6,46', add = 34332;
var numbers = listOfNumbers.split(',');
if(numbers.indexOf(add)!=-1) {
numbers.push(add);
}
listOfNumbers = numbers.join(',');
Basically i convert the string into an array, check the existence of the value using indexOf(), adding only if it doesn't exist.
I then convert the value back to a string using join.
If that is a string, you can use the .split() and .join() functions, as well as .push():
var data = '3434,346,1,6,46';
var arr = data.split(',');
var add = newInt;
arr.push(newInt);
data = arr.join(',');
If that is already an array, you can just use .push():
var data = [3434,346,1,6,46];
var add = newInt;
data.push(add);
UPDATE: Didn't read the last line to check for duplicates, the best approach I can think of is a loop:
var data = [3434,346,1,6,46];
var add = newInt;
var exists = false;
for (var i = 0; i < input.length; i++) {
if (data[i] == add) {
exists = true;
break;
}
}
if (!exists) {
data.push(add);
// then you would join if you wanted a string
}
You can also use a regular expression:
function appendConditional(s, n) {
var re = new RegExp('(^|\\b)' + n + '(\\b|$)');
if (!re.test(s)) {
return s + (s.length? ',' : '') + n;
}
return s;
}
var nums = '3434,346,1,6,46'
alert( appendConditional(nums, '12') ); // '3434,346,1,6,46,12'
alert( appendConditional(nums, '6') ); // '3434,346,1,6,46'
Oh, since some really like ternary operators and obfustically short code:
function appendConditional(s, n) {
var re = new RegExp('(^|\\b)' + n + '(\\b|$)');
return s + (re.test(s)? '' : (''+s? ',':'') + n );
}
No jQuery, "shims" or cross-browser issues. :-)