Use spread syntax instead of for loop - javascript

I'd like to reduce this code using the spread syntax to remove the for loop, any ideas?
function shiftChar() {
let aCharArray = prompt("Enter a word").split("");
for (let i = 0; i < aCharArray.length; i++) {
aCharArray[i] = String.fromCharCode(aCharArray[i].charCodeAt(0) + 1);
}
alert(aCharArray);
}
This doesn't work
function shiftChar() {
let aCharArray = prompt("Enter a word").split("");
aCharArray = String.fromCharCode(...aCharArray.charCodeAt(0) + 1);
alert(aCharArray);
}

Spread syntax (it's not an operator!) is not a replacement for loops, it's a replacement for apply.
You can do
const string = prompt("Enter a word");
const charCodes = [];
for (let i = 0; i < aCharArray.length; i++) {
aCharCodes[i] = aString.charCodeAt(i) + 1;
}
though and then use
String.fromCharCode(...charCodes)
instead of
String.fromCharCode.apply(String, charCodes)

For every element in your array you are doing some manipulation, charCodeAt(0) + 1, so it is probably best you use map.
map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results.
You can use the spread syntax in order to update the contents of your variable aCharArray from the array.
Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments
function shiftChar() {
let aCharArray = prompt("Enter a word").split("").map(x => x.charCodeAt(0) + 1);
aCharArray = String.fromCharCode(...aCharArray);
alert(aCharArray);
}

A minified solution not using spread:
function shiftChar() {
alert(
prompt("Enter a word").split("")
.map(letter => String.fromCharCode(letter.charCodeAt(0) + 1));
);
}
A (strange) minified solution using spread:
function shiftChar() {
alert(
[...prompt("Enter a word")].map(letter => (
String.fromCharCode(letter.charCodeAt(0) + 1)
)
);
}

Related

Dynamic masked input according to data [duplicate]

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"))

Convert string to characters then check each character , scribble like behavior

I've already did this using a loop but our instructor said that it can be done with a shorter and simpler method/function. We are not allowed to use for loops or foreach. We can only use es6 related code.
This is my code.
var total = 0
let givenWord = "cabbage"
let pointsTable = new Map([['a',1],['e',1],['i',1],['o',1],['u',1],['l',1],['n',1],['r',1],['s',1],['t',1],
['d',2],['g',2],['b',3],['c',3],['m',3],['p',3],['f',4],['h',4],['v',4],['y',4],['k',5],['j',8],['x',8],['q',10],['z',10]])
for(let [...letters] of givenWord){
for(let [key,value] of pointsTable){
if(letters == key){
total = total + value;
console.log("Total value is " + total)
}
}
}
my problem here is that my loops take up too many lines of code. How do I transform this one into simpler code or using a function/method ? using only ES6?
Ok, I created a sort ES6 way to return the chars in an array and run a check function on them:
const pointsTable = new Map([['a',1],['e',1],['i',1],['o',1],['u',1],['l',1],['n',1],['r',1],['s',1],['t',1],
['d',2],['g',2],['b',3],['c',3],['m',3],['p',3],['f',4],['h',4],['v',4],['y',4],['k',5],['j',8],['x',8],['q',10],['z',10]])
// With ES6
const text= 'abcdefg';
const result = [...text].reduce((acc, cur) => {
return acc + pointsTable.get(cur)
}, 0);
console.log(result);
An other way you could do this is write a while loop and use the String.split(), String.slice() or String.substring() methods to reduce the string to the chars
You can use recursion for this task:
var total = 0
let givenWord = "cabbage"
let pointsTable = new Map([['a',1],['e',1],['i',1],['o',1],['u',1],['l',1],['n',1],['r',1],['s',1],['t',1],
['d',2],['g',2],['b',3],['c',3],['m',3],['p',3],['f',4],['h',4],['v',4],['y',4],['k',5],['j',8],['x',8],['q',10],['z',10]])
const countTotal = (arr, map, points = 0) => {
if(arr.length === 0) return points
points += map.get(arr.splice(0,1)[0])
return countTotal(arr, map, points)
}
console.log(countTotal([...givenWord],pointsTable))
Using the split method it will separate the text into the individual letters. Then you can use the map method to iterate through each of those letters and do a check within that.
const test = 'abcdefg'
let total = 0;
let pointsTable = new Map([['a',1],['e',1],['i',1],['o',1],['u',1],['l',1],
['n',1],['r',1],['s',1],['t',1],
['d',2],['g',2],['b',3],['c',3],['m',3],['p',3],['f',4],['h',4],['v',4],
['y',4],['k',5],['j',8],['x',8],['q',10],['z',10]])
test.split('').map(function(letter){
let value = pointsTable.get(letter)
total += value;
});
Here's the shortest way I can think of :
var total = 0
let givenWord = "cabbage"
let pointsTable = new Map([['a',1],['e',1],['i',1],['o',1],['u',1],['l',1],['n',1],['r',1],['s',1],['t',1],
['d',2],['g',2],['b',3],['c',3],['m',3],['p',3],['f',4],['h',4],['v',4],['y',4],['k',5],['j',8],['x',8],['q',10],['z',10]])
let total = givenWord.split``.reduce((a,l)=>a+pointsTable.get(l),0)
console.log("Total value is " + total)
details :
let total = // assign to total
givenWord // the givenword
.split`` // splited to get an array of characters
.reduce( // call reduce on the array
(a, l) => { // first arg of reduce is a function
// called for each elements of the array
// arguments are the accumulator, the letter
a + pointsTable.get(l) // add the letter score to the accumulator
},
0 // set default value of accumulator (2nd arg of reduce)
)
fn`` documentation (look at section tagged template),
reduce documentation

function parameters from variables fail as string javascript

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)

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 do I convert strings in an array to numbers using forEach?

I am trying to sum the contents of an array like these:
var cardsBen = [10,2]
var cardsAmy = [4,10]
When I use a for loop, it works.
for(var i = 0; i < cardsBen.length; i++){
cardsBen[i] = Number(cardsBen[i]);
}
When I use forEach, it doesn't convert.
cardsAmy.forEach(function(item)
{
Number(item);
});
I know this because, when I then reduce the arrays, I get 12 for Ben and 410 for Amy.
var sumBen = cardsBen.reduce(function(sum, nbr){return sum + nbr});
var sumAmy = cardsAmy.reduce(function(sum, nbr){return sum + nbr});
Primitive values can't be mutated. So when doing Number(item) you have to assign that back to the array like:
cardsAmy.forEach(function(item, i) {
cardsAmy[i] = Number(item);
});
And you can do that directly in reduce (without needing the above forEach code) like:
var sumBen = cardsBen.reduce(function(sum, nbr) { return sum + Number(nbr); }, 0);
// ^^^^^^^ ^
You could use reduce with an implicit casting to number with an unary plus +.
sum = array.reduce(function (s, v) {
return s + +v;
}, 0);

Categories