How can I stringify output from a for loop? - javascript

I have the following for loop and I would like the output of the loop to be stringified into a query string as shown in the desired output below. I'm using the qs npm package for stringifying URLs.
What's the best way of going about getting the desired output?
for (i = 0; i < 2; i++) {
var foo = "pr" + [i] + "va";
var bar = "value";
};
//Desired output: ?pr0va=value&pr1va=value

Instead of creating variables - create String and do concatenation in every loop.
Check my code snippet.
var query = "";
var size = 2;
for (i = 0; i < size; i++) {
query += "pr" + [i] + "va=value";
if (i+1<size)
query += "&";
};
console.log(query);

This should work for you.
function test () {
var i =0;
var arr = [];
for(i=0;i<2;i++) {
arr.push( "pr" + [i] + "va=value" );
}
console.log('?' + arr.join('&').toString())
}

Something like this?
var output = '?';
for (i = 0; i < 2; i++) {
var foo = "pr" + [i] + "va";
var bar = "value";
output += foo + "=" + bar + "&";
};
console.log(output);
//Desired output: ?pr0va=value&pr1va=value

You can do it like this.
var output = "?";
for (i = 0; i < 2; i++) {
output += "pr" + [i] + "va=value&";
};
console.log(output.slice(0, -1))

If I were to review such code I would prefer to see the following:
Avoid concatenation.
Use of functional programming.
Reasonable usage of 3rd parties - so yes for querystring
All of those are for readability, simplicity and maintainability benefits. And I admit it is arguable.. so please don't argue :)
I will use your code as a baseline and improve from there
for (i = 0; i < 2; i++) {
var foo = "pr" + [i] + "va";
var bar = "value";
};
Note that your snippet is incomplete, and so, at the beginning mine will not be complete too, but I'll get there
Avoid concatenation
I will avoid concatenation using template literal
for (i = 0; i < 2; i++) {
`pr${i}va=value`;
};
Use of functional programming
I will iterate over numbers using an array, and reduce to construct an object
const queryParams = Array(2).fill().reduce((object, value, index) => {
object[`pr${index}va`] = 'value';
return object;
} , {} )
Using 3rd parties
Now I will use querystring to turn queryParams to a query string
return querystring.stringify(queryParams);
All together now
/**
* #param {number} count - number of query parameters to generate
* #returns {string} query string. for example for count=2 will return `pr1va=value&pr2va=value`
**/
function generateQueryString(count=2){
const queryParams = Array(count).fill().reduce((object, value, index) => { // convert N number to key-value map using reduce
object[`pr${index}va`] = 'value';
return object;
} , {} );
return querystring.stringify(queryParams);
}

You can create an array of size, loop and then join it:
function createString(size) {
return new Array(size).fill(0).map((v, i) => {
return "pr" + i + "va=value";
}).join("&");
}
console.log(createString(2));

Related

javascript transform text array

I use a react component which work like this
<FontAwesomeIcon icon={faCoffee} />
it take a font awesome icon let say address-book it add fa before, delete hyphen and uppercase the first letter of each world.
address-book become faAddressBook
copyright become faCopyright
arrow-alt-circle-down become faArrowAltCircleDown
Is it possible to create a javascript function which take an array like this
["address-book","copyright","arrow-alt-circle-down"]
and transform it in an array like that
["faAddressBook","faCopyright","faArrowAltCircleDown"]
There are some ways to do it. Like using regular expression. However, your requirement is simple, so it can be easily done with JavaScript split method. Please check the following implemented function.
function formatArray(str)
{
str = str.split("-");
for (var i = 0, x = str.length; i < x; i++) {
str[i] = str[i][0].toUpperCase() + str[i].substr(1);
}
return 'fa' + str.join("");
}
var givenArr = ["address-book","copyright","arrow-alt-circle-down"];
for( var i = 0; i < givenArr.length; i++) {
givenArr[i] = formatArray(givenArr[i]);
console.log(givenArr[i]+ '\n');
}
You can do the following with Array's map() and forEach():
var arr = ["address-book","copyright","arrow-alt-circle-down"];
function upperCase(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
var outPut = arr.map(function(item){
var temp = item.split('-');
var temp2 = [];
temp.forEach(function(data){
temp2.push(upperCase(data))
});
return 'fa' + temp2.join('')
})
console.log(outPut);
Looks like there's two essential steps here. First, we need to prepend fa onto each string, and second, we need to convert them from kebab-case to camelCase.
So just write a function for each of those conversions, then run your array through a map using each of them:
const kebabs = ["address-book","copyright","arrow-alt-circle-down"];
function kebabToCamel(str) {
return str.replace(/-(\w)/g, m => m[1].toUpperCase());
}
function prependFa(str) {
return "fa-" + str;
}
console.log(kebabs.map(prependFa).map(kebabToCamel))

How to change Key of an object dynamically

I have an object like this:
var obj{};
I want to set object values dynamically like so:
for(i=0;i<10;i++)
{
quest='quest'+i;
header='header'+i;
$(obj).data(quest,{header:i});
quest,header=0;
}
I'm expecting object to be saved like:
obj{quest1:{header1:1},
quest2:{header2:2}
quest3:{header3:3}
But they are saved like:
obj{quest1:{header:1},
quest2:{header:2},
quest3:{header:3},
The header-key in my object is not getting the actual value. but simply save as "header"..
Could you please guide me here?
You can write:
var obj = {};
for(i=1; i<11; i++) {
quest='quest'+i;
header='header'+i;
obj[quest] = {};
obj[quest][header] = i;
}
In your code your loop starts with i = 0 but the properties start by 1.
var quest, header, obj = {};
for (i = 0; i < 10; i += 1) {
quest = 'quest' + (i + 1);
header = 'header' + (i + 1);
obj[quest] = {};
obj[quest][header] = (i + 1);
}
You cannot have a variable key in an object literal.

Javascript string manipulation url

My problem is I am trying to extract certain things from the url. I am currently using
window.location.href.substr()
to grab something like "/localhost:123/list/chart=2/view=1"
What i have now, is using the index positioning to grab the chart and view value.
var chart = window.location.href.substr(-8);
var view = window.location.href.substr(-1);
But the problem comes in with I have 10 or more charts. The positioning is messed up. Is there a way where you can ask the code to get the string between "chart=" and the closest "/"?
var str = "/localhost:123/list/chart=2/view=1";
var data = str.match(/\/chart=([0-9]+)\/view=([0-9]+)/);
var chart = data[1];
var view = data[2];
Of course you may want to add in some validation checks before using the outcome of the match.
Inspired by Paul S. I have written a function version of my answer:
function getPathVal(name)
{
var path = window.location.pathname;
var regx = new RegExp('(?:/|&|\\?)'+name+'='+'([^/&,]+)');
var data = path.match(regx);
return data[1] || null;
}
getPathVal('chart');//2
Function should work for fetching params from standard get parameter syntax in a URI, or the syntax in your example URI
Here's a way using String.prototype.indexOf
function getPathVar(key) {
var str = window.location.pathname,
i = str.indexOf('/' + key + '=') + key.length + 2,
j = str.indexOf('/', i);
if (i === key.length + 1) return '';
return str.slice(i, j);
}
// assuming current path as described in question
getPathVar('chart');
You could split your string up, with "/" as delimiter and then loop through the resulting array to find the desired parameters. That way you can easily extract all parameters automatically:
var x = "/localhost:123/list/chart=2/view=1";
var res = {};
var spl = x.split("/");
for (var i = 0; i < spl.length; i++) {
var part = spl[i];
var index = part.indexOf("=");
if (index > 0) {
res[part.substring(0, index)] = part.substring(index + 1);
}
}
console.log(res);
// res = { chart: 2, view: 1}
FIDDLE

Adding Multiple Arguments into an built in function, from a function

I'm trying to add String.fromCharCode(). And adding it into a function that renames it like so:
function from() {
var ar = arguments.length;
var argumentss = '';
for (var i = 0; i < ar; i++) {
var a = argumentss + '\'' + arguments[i];
if (i == ar - 1) {
argumentss = a + '\''
} else {
argumentss = a + '\', '
}
}
var arg = eval(argumentss);
return String.fromCharCode(arg)
}
I need to do this, so don't say that there is no reason to do this, since the way im actually using it there is a reason.
What im trying to do is make it possible to do:
from(65,66,67) //returns ABC
Without doing function from(a,b,c)
Since with the fromCharCode you can do as many arguments as you want. It would also be useful if there was a custom fromCharCode function. Thanks
Is this what you want?
function from() {
var result = '';
for (var i = 0; i < arguments.length; i++) {
result += String.fromCharCode(arguments[i]);
}
return result;
}
from(65,66,67)
//result -> ABC
Does this address your problem? Call this once at the beginning:
String.from = String.fromCharCode.bind(String)
and use later:
String.from(65, 66, 67) //"ABC"
Using built-in String.fromCharCode().

Javascript token replace/append

I have a string that looks something like the following 'test:1;hello:five;just:23'. With this string I need to be able to do the following.
....
var test = MergeTokens('test:1;hello:five;just:23', 'yes:23;test:567');
...
The end result should be 'test:567;hello:five;just:23;yes:23' (note the exact order of the tokens is not that important).
Just wondering if anyone has any smart ideas of how to go about this. I was thinking a regex replace on each of the tokens on right and if a replace didn't occur because there was not match just append it. But maybe there is better way.
Cheers
Anthony
Edit: The right side should override the left. The left being what was originally there and the right side being the new content. Another way of looking at it, is that you only keep the tokens on the left if they don't exist on the right and you keep all the tokens on the right.
#Ferdinand
Thanks for the reply. The problem is the efficiency with which the solution you proposed. I was initially thinking down similar lines but discounted it due to the O(n*z) complexity of the merge (where n and z is the number tokens on the left and right respectively) let alone the splitting and joining.
Hence why I was trying to look down the path of a regex. Maybe behind the scenes, regex is just as bad or worse, but having a regex which removes any token from the left string that exists on the right (O(n) for the total amount of token on the right) and then just add the 2 string together (i.e. vat test = test1 + test2) seems more efficient. thanks
I would use join() and split() to create some utility functions to pack and unpack your token data to an object:
// Unpacks a token string into an object.
function splitTokens(str) {
var data = {}, pairs = str.split(';');
for (var i = 0; i < pairs.length; ++i) {
var pair = pairs[i].split(':');
data[pair[0]] = pair[1];
}
return data;
}
// Packs an object into a token string.
function joinTokens(data) {
var pairs = [];
for (var key in data) {
pairs.push(key + ":" + data[key]);
}
return pairs.join(';');
}
Using these, merging is easy:
// Merges all token strings (supports a variable number of arguments).
function mergeTokens() {
var data = {};
for (var i = 0; i < arguments.length; ++i) {
var d = splitTokens(arguments[i]);
for (var key in d) {
data[key] = d[key];
}
}
return joinTokens(data);
}
The utility functions are also useful if you want to extract some keys (say,"test") and/or check for existence:
var data = splitTokens(str);
if (data["test"] === undefined) {
// Does not exist
} else {
alert("Value of 'test': " + data["test"]);
}
The following is what I ended thiking about. What do you guys recon?
Thanks
Anthony
function Tokenizer(input, tokenSpacer, tokenValueSpacer) {
this.Tokenizer = {};
this.TokenSpacer = tokenSpacer;
this.TokenValueSpacer = tokenValueSpacer;
if (input) {
var TokenizerParts = input.split(this.TokenSpacer);
var i, nv;
for (i = 0; i < TokenizerParts.length; i++) {
nv = TokenizerParts[i].split(this.TokenValueSpacer);
this.Tokenizer[nv[0]] = nv[1];
}
}
}
Tokenizer.prototype.add = function(name, value) {
if (arguments.length == 1 && arguments[0].constructor == Object) {
this.addMany(arguments[0]);
return;
}
this.Tokenizer[name] = value;
}
Tokenizer.prototype.addMany = function(newValues) {
for (nv in newValues) {
this.Tokenizer[nv] = newValues[nv];
}
}
Tokenizer.prototype.remove = function(name) {
if (arguments.length == 1 && arguments[0].constructor == Array) {
this.removeMany(arguments[0]);
return;
}
delete this.Tokenizer[name];
}
Tokenizer.prototype.removeMany = function(deleteNames) {
var i;
for (i = 0; i < deleteNames.length; i++) {
delete this.Tokenizer[deleteNames[i]];
}
}
Tokenizer.prototype.MergeTokenizers = function(newTokenizer) {
this.addMany(newTokenizer.Tokenizer);
}
Tokenizer.prototype.getTokenString = function() {
var nv, q = [];
for (nv in this.Tokenizer) {
q[q.length] = nv + this.TokenValueSpacer + this.Tokenizer[nv];
}
return q.join(this.TokenSpacer);
}
Tokenizer.prototype.toString = Tokenizer.prototype.getTokenString;
i am a few years late, but i think this is what you are looking for:
function MergeTokens(input, replace){
var replaceTokens = replace.split(";");
for(i=0; i<replaceTokens.length; i++){
var pair = replaceTokens[i].split(":");
var result = input;
regString = "\\b" + pair[0] + ":[\\w]*\\b";
var reg = new RegExp(regString);
if(reg.test(result)){
result = result.replace(reg, replaceTokens[i]);
}
else{
result = result + replaceTokens[i];
}
}
return result;
}

Categories