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))
Related
This question already has answers here:
Dynamic regex pattern in JavaScript
(4 answers)
Closed 2 years ago.
I have a response and it returns "XXX-XXX" or "XX-XXXX"
const formatUnitCode = (value, format) => {}
So basically, I want to see as formatUnitCode("123456", "XX-XXX") --> "12-3456"
I don't want to use if else because it may come in the future as XX-XX-XX
Can someone help me create this function?
I tried to do with regex but I think it is not possible to pass variable instead of {2} and {4}
const formatCode = (val) => val.replace(/(\d{2})(\d{4})/g, "$1-$2");
Is this what you would like to do?
const func = (val, first_digit) => {
let regex = new RegExp("(\\d{" + first_digit + "})(\\d{" + (6-first_digit) + "})","g");
return val.replace(regex,"$1-$2");
};
You can use simple for loop make a dynamic string format method.
const formatUnitCode = (str, format) => {
let result = '';
let j = 0;
for (let i = 0, l = format.length; i < l; i += 1) {
if (format[i] === 'X') {
result += str[j];
j += 1;
} else result += format[i];
}
for (; j < str.length; j += 1) result += str[j];
return result;
};
console.log(formatUnitCode('123456', 'XX-XXX'));
console.log(formatUnitCode('123456', 'XXX-XXX'));
console.log(formatUnitCode('123456', 'XX-XXXX'));
console.log(formatUnitCode('123456', 'XX-XX-XX'));
You can't use variables in RegExp literals, but you can when you use the RegExp() constructor to build the pattern as a string instead.
const formatStr = (val, format) => {
let ptn = format.split('-').map(part => '(.{'+part.length+'})').join('');
match = val.match(new RegExp(ptn));
match && console.log(match.slice(1).join('-'));
};
It's instructive to console.log() the ptn var to see what's happening there. We're using your arbitrary "X"-based format to derive a new, dynamic RegExp which will be used in a multi-match RegExp to grab the parts.
formatStr('123456', 'xxx-xxx'); //"123-456"
formatStr('123456', 'xx-xxxx'); //"12-3456"
This should work for any mask regardless of the letters used (you can control that behaviour by changing matcher regex). Personally, I think it's a more elastic approach than just trying to match the given mask with a regex.
const replaceWithFiller = (filler, str, matcher = /[a-zA-z]/g) => {
const arr = filler.split('');
return str.replace(matcher, () => arr.shift());
};
console.log(replaceWithFiller('123456', 'XXX-XXX')); //"123-456"
console.log(replaceWithFiller('123456', 'XX-XX-XX')); // "12-34-56"
console.log(replaceWithFiller('123456', 'XX-XXXX')); //"12-3456"
console.log(replaceWithFiller('123456', 'aa-aaaa')); // also "12-3456"
you can pass parameters to your regex using template literals:
const formatCode = (val, format) => {
const lengthFirstBlock = format.indexOf('-');
const lehgthSecondBlock = format.length - format.indexOf('-');
const regex = new RegExp(`(\\d{${lengthFirstBlock}})(\\d{${lehgthSecondBlock}})`, 'g');
return val.replace(regex, "$1-$2");
}
console.log(formatCode("123456", "XX-XXX"))
console.log(formatCode("123456", "XXX-XX"))
This Works:
setTheme('#222','#000','wheat','red','wheat','none','none');
This does not work:=
var theme01 = "'#222','#000','wheat','red','wheat','none','none'"; <br>
setTheme(theme01);
console.log(theme01) = '#222','#000','wheat','red','wheat','none','none'
So the conversion to string messes it up somehow?
I will be toggling through various themes before capturing the canvas? I had it all working with CSS, but canvas does not capture css changes or css injection. So I now have it all ready to go using Vanilla Javascript, but need help after hours of testing searching just to pass a variable to my function. Grrr. Help!
I have only been at this for a couple of weeks, so it's a learning curve after working only in Wordpress.
function setTheme(topp,bott,txt,hlin,vlin,fOrb,sOrb) {
var xx = document.querySelectorAll(".hlin");
for (var i = 0; i < xx.length; i++) {
xx[i].style.stroke = hlin;
}
var xx = document.querySelectorAll(".vlin");
for (var i = 0; i < xx.length; i++) {
xx[i].style.stroke = vlin;
}
var xx = document.querySelectorAll(".txt");
for (var i = 0; i < xx.length; i++) {
xx[i].style.fill = txt;
}
document.getElementById("svg_20").style.fill = topp;
document.getElementById("svg_1").style.fill = bott;
document.getElementById("svg_2").style.fill = bott;
document.getElementById("svg_3").style.stroke = txt;
document.getElementById("svg_5").style.stroke = txt;
document.getElementById("svg_21").style.fill = fOrb;
document.getElementById("svg_21").style.stroke = sOrb;
};
Yep, you can’t exchange a list of parameters for a comma-separated string. You should use a data structure to store them, like an array or object. Here’s an example of how it would work with an object.
var theme01 = { topp: '#222', bott: '#000', txt: 'wheat' };
function setTheme ( options ) {
document.getElementById("svg_20").style.fill = options.topp;
document.getElementById("svg_1").style.fill = options.bott;
document.getElementById("svg_3").style.fill = options.txt;
}
setTheme( theme01 )
The string will be one parameter for your function. You can use Function.apply )1 with a splitted string as second parameter, or even simpler, use the spread operator 2). Demo:
1) Function.apply
2) spread operator
( () => {
const log = str => document.querySelector("#result").textContent += `${str} \n`;
const parameterString = "#222,#000,wheat";
// no dice
log("someFn(parameterString) => no dice");
someFn(parameterString);
// use apply
log("\nsomeFn.apply(null, parameterString.split(\",\")) => ah yes, that works");
someFn.apply(null, parameterString.split(","));
// or use spread operator
log("\nsomeFn(...parameterString.split(\",\")) => ah yes, that works too");
someFn(...parameterString.split(","));
function someFn(p1, p2, p3) {
log(p1);
log(p2);
log(p3);
}
})();
<pre id="result"></pre>
You can pass it as an array using spread syntax, you cannot however pass a string of items and have them be multiple parameters.
function setTheme(topp, bott, txt, hlin, vlin, fOrb, sOrb) {
console.log(topp)
console.log(bott)
console.log(txt)
console.log(hlin)
console.log(vlin)
console.log(fOrb)
console.log(sOrb)
}
let items = ['#222', '#000', 'wheat', 'red', 'wheat', 'none', 'none']
setTheme(...items)
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));
I have an algorithm where the user will enter a string and I will parse it into an array of 2+ dimensions. So, for example, the user can enter 1,2,3;4,5,6 and set the text to be parsed by the semicolon and the comma. The first pass through will create an array with 2 entries. The second pass through will create a 3 entry array in both prior spots.
The user can add or remove the number of text items to be used to parse the original string such as the semicolon or comma, meaning the resulting array can have as many dimensions as parsing items.
This doesn't seem like a difficult problem, but I have run into some snags.
Here is my code so far.
vm.parsers = [';', ','];
vm.inputString = "1,2,3,4,5;6,7,8,9,10";
function parseDatasetText( )
{
vm.real = vm.parseMe( vm.inputString, 0);
};
function parseMe( itemToParse, indexToParse )
{
if ( indexToParse < vm.parsers.length )
{
console.log('Parsing *'+itemToParse+'* with '+vm.parsers[indexToParse]);
var tempResults = itemToParse.split( vm.parsers[indexToParse] );
for (var a=0; a<tempResults.length; a++)
{
console.log('Pushing '+tempResults[a]);
tempResults[a] = vm.parseMe( tempResults[a], parseInt( indexToParse ) + 1 )
console.log('This value is '+tempResults[a]);
}
}else
{
console.log('Returning '+itemToParse);
return itemToParse
}
};
As you can see from the console logs, the algorithm spits out an undefined after the last parse, and the final answer is undefined.
Maybe I just haven't slept enough, but I was thinking that the array would recursively populate via the splits?
Thanks
function parseDatasetText(){
//composing parser from right to left into a single function
//that applies them from left to right on the data
var fn = vm.parsers.reduceRight(
(nextFn, delimiter) => v => String(v).split(delimiter).map(nextFn),
v => v
);
return fn( vm.inputString );
}
Don't know what else to add.
You can use a simple recursive function like the following (here an example with 3 different delimiters):
function multiSplit(xs, delimiters) {
if (!delimiters.length) return xs;
return xs.split(delimiters[0]).map(x => multiSplit(x, delimiters.slice(1)));
}
data = '1:10,2:20,3:30;4:40,5:50,6:60';
res = multiSplit(data, [';', ',', ':']);
console.log(res)
The following function should suit your requirements, please let me know if not
var parsers = [';', ',', ':'],
inputString = "1:a,2:b,3:c,4:d,5:e;6:f,7:g,8:h,9:i,10:j",
Result = [];
function Split(incoming) {
var temp = null;
for (var i = 0; i < parsers.length; i++)
if (incoming.indexOf(parsers[i]) >= 0) {
temp = incoming.split(parsers[i]);
break;
}
if (temp == null) return incoming;
var outgoing = [];
for (var i = 0; i < temp.length; i++)
outgoing[outgoing.length] = Split(temp[i])
return outgoing;
}
Result = Split(inputString);
try it on https://jsfiddle.net/cgy7nre1/
Edit 1 -
Added another inputString and another set of parsers: https://jsfiddle.net/cgy7nre1/1/
Did you mean this?
var inputString = "1,2,3,4,5;6,7,8,9,10";
var array=inputString.split(';');
for (var i=0;i<array.length;i++){
array[i]=array[i].split(',');
}
console.log(array);
I am new for javascript, I have a one long string i want to split after 3rd commas and change diffferent format. If you are not understand my issues. Please see below example
My string:
var test= "10,Idly(3 Pcs),200,10,Ghee Podi Idly,300";
I want output like this:(Each item should be in next line)
Idly(3 Pcs) - 10 = 200
Ghee Podi Idly - 10 = 300
How to change like this using JavaScript?
Just copy and paste it. Function is more dynamic.
Example Data
var testData = "10,Idly(3 Pcs),200,10,Ghee Podi Idly,300";
Function
function writeData(data){
data = data.split(',');
var tempLine='';
for(var i=0; i<data.length/3; i++) {
tempLine += data[i*3+1] + ' - ' + data[i*3] + ' = ' + data[i*3+2] + '\n';
}
alert(tempLine);
return tempLine;
}
Usage
writeData(testData);
Use split method to transform the string in a array and chunk from lodash or underscore to separate the array in parts of 3.
// A custom chunk method from here -> http://stackoverflow.com/questions/8495687/split-array-into-chunks
Object.defineProperty(Array.prototype, 'chunk_inefficient', {
value: function(chunkSize) {
var array=this;
return [].concat.apply([],
array.map(function(elem,i) {
return i%chunkSize ? [] : [array.slice(i,i+chunkSize)];
})
);
}
});
var test= "10,Idly(3 Pcs),200,10,Ghee Podi Idly,300";
var arr = test.split(',');
var arr = arr.chunk_inefficient(3);
arr.forEach(function (item) {
console.log(item[1]+' - '+item[0]+' = '+item[2]);
});
You can use split to split the string on every comma. The next step is to iterate over the elements, put the current element into a buffer and flush the buffer if it's size is three. So it's something like:
var tokens = test.split(",");
var buffer = [];
for (var i = 0; i < tokens.length; i++) {
buffer.push(tokens[i]);
if (buffer.length==3) {
// process buffer here
buffer = [];
}
}
If you have fix this string you can use it otherwise validate string.
var test= "10,Idly(3 Pcs),200,10,Ghee Podi Idly,300";
var test2= test.split(",");
var temp_Str= test2[1]+' - '+test2[0]+' = '+test2[2]+'\n';
temp_Str+= test2[4]+'-'+test2[3]+' = '+test2[5];
alert(temp_Str);