I have this:
function myalert(x)
{
alert("hey + " x)
}
i am calling a afunction with different parameters
myalert("A");
myalert("B");
myalert("C");
myalert("A");
myalert("B");
myalert("C");
myalert("A");
myalert("B");
myalert("C");
can I avoid that ugly repetition?
update=But what if 2 parameters? How will I make the "LIST" you are talking about?
Example:
function myalert(x,y)
{
alert(y + "hey + " x )
}
myalert("A", "X");
myalert("B", "X");
How can i make a list of this?
Loop it. You can get function arguments using arguments and their count arguments.length.
function myalert()
{
var count = arguments.length;
for(var i = 0; count > i; i++) {
alert("hey + " + arguments[i]);
}
}
myalert('a', 'b', 'c'); // alerts a, alerts b, alerts c
Put all parameters in an array, then use a loop.
var params = ['A', 'B', 'C'];
for (var i = 0, l = parmas.length; i < l; i++) {
myalert(params[i]);
}
or:
['A', 'B', 'C'].forEach(function(e) {
myalert(e);
});
myalert(['A', 'B', 'C']);
function myalert(dataArray)
{
dataArray.forEach(function(e) {
alert("hey " + x);
});
}
Related
So I have a method that returns an object that returns referrals of a individual
function getReferredUsers(userId) {
const usersMap = {
a : ['b', 'c'],
b: ['d', 'e'],
d: ['f', 'g']
};
return usersMap[userId] || [];
}
So, in the example a directly referred b and c. While b directly referred d and e and so on.
so d and e becomes indirect referrals for a. f,g are indirect for a as d is also an indirect for a.
For direct we get 3 points for indirect we get 2.
We need to calculate total points for a.
I tried
var _opSum = 0;
function getTotalReferralBonus(userId, bonus) {
if(bonus === 0)
return 0;
let directUsers = getReferredUsers(userId);
if(directUsers.length > 0) {
for(let user of directUsers) {
_opSum = getTotalReferralBonus(user, bonus -1) + bonus;
}
}else {
_opSum += getTotalReferralBonus(userId, bonus -1);
}
return _opSum;
}
But it does not work.
What am I doing wrong ?
UPDATE
Total points that a would get is 3 + 3 (for b,c) + 2 + 2 (for d,e through b) + 1 + 1 (for f,g through d through b) = 12
You need a local variable _opSum and you need to get all bonusses from the nested Id.
function getReferredUsers(userId) {
const usersMap = {
a: ['b', 'c'],
b: ['d', 'e'],
d: ['f', 'g']
};
return usersMap[userId] || [];
}
function getTotalReferralBonus(userId, bonus) {
var _opSum = 0; // local variable
if (bonus === 0) return 0;
let directUsers = getReferredUsers(userId);
if (directUsers.length > 0) {
for (let user of directUsers) {
_opSum += getTotalReferralBonus(user, bonus - 1) + bonus; // add all instead of assignment
}
} else {
_opSum += getTotalReferralBonus(userId, bonus - 1);
}
return _opSum;
}
console.log(getTotalReferralBonus('a', 3));
I'm creating a reusable function with multiple/unknown number of variable(s) and one callback.
//the number of variable will be dynamic
var a = "this is a.";
var b = "this is b.";
function callback(){
console.log('callback successful');
}
//totalUp() will be reusable function
function totalUp(allVariables, callback){
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
//how do I pass unknown number of arguments(a and b) into one parameter?
totalUp({a,b},callback);
In my code above I'm passing a and b in form of object which doesn't work.
With ES6
You can use parameter destructuring for it:
function test(callback, ...params) {
console.log(params); // ["a", "b"];
console.log('Here are the complete list: ' + params.join(", ") + '.');
}
test(callback, "a", "b");
Without ES6
function test(params, callback) {
console.log(params); // ["a", "b"];
console.log('Here are the complete list: ' + params.join(", ") + '.');
}
test(["a", "b"], callback);
let allVars = [
"this is a.",
"this is b.",
]
You can have some more variables inserted into allVars and therefore you can have an unknown number of variables.
When you pass it to the function, you have 2 options.
First one is to pass array and to use it as array
function totalUp(allVars, callback){
let allVariables;
for (let i = 0; i<allVars.length; i++) {
allVariables += allVars[i] + ", ";
}
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
As Marvin mentioned, you can also use .join() to get the all variables in the array in one string.
function totalUp(allVars, callback){
let allVariables = allVars.join(", ");
console.log('Here are the complete list: ' + allVariables + '.');
callback();
}
Second one is to pass it as an object
let allVars = {
a: "this is a.",
b: "this is b."
}
I would change the sinature of the dunction and take first the necessary callback as first parameter and then take the dynamic arguments.
function upTo(cb, ...params) {
cb(...params);
}
function cb(...params) {
params.forEach(v => console.log(v));
}
upTo(cb, 1, 2, 3);
ES5
function upTo(cb) {
cb.apply(null, Array.prototype.slice.call(arguments, 1));
}
function cb() {
Array.prototype.slice.call(arguments).forEach(function (v) { console.log(v); });
}
upTo(cb, 1, 2, 3);
To all string manipulation maestros, this might be an interesting exercise. Given a string containing "x" or "xx" scattered in quasi-random places (like a DNA sequence), I need to permutate this string by varying the "x" in it. Each instance of "x" can be a singular "x" or a double "xx", and the entire string should contain all possible combinations of "x" and "xx".
Given the string "ooxooxoo", the output would be
[
"ooxxooxoo",
"ooxooxxoo",
"ooxxooxxoo"
]
Given the string "ooxxooxoo", the output would be
[
"ooxooxoo",
"ooxooxxoo",
"ooxxooxxoo"
]
Given the string "ooxooxoox", the output would be
[
"ooxxooxoox",
"ooxooxxoox",
"ooxooxooxx",
"ooxxooxxoox",
"ooxxooxooxx",
"ooxooxxooxx",
"ooxxooxxooxx"
]
And so on so forth. In no cases should the output ever contain three or more contiguous x's.
UPDATE:
After a bit of research, I settled on a solution based on Heap's permutation algorithm:
function heapsPermute(aInput, aOutput, n) {
var swap = function(n1, n2) {
var sTemp = aInput[n1];
aInput[n1] = aInput[n2];
aInput[n2] = sTemp;
};
n = n || aInput.length;
if (n===1) {
// Add only unique combination
var sCombo = aInput.join(' ');
if (aOutput.indexOf(sCombo)<0) aOutput.push(sCombo);
} else {
for (var i=1, j; i<=n; ++i) {
heapsPermute(aInput, aOutput, n-1);
j = (n%2) ? 1 : i;
swap(j-1, n-1);
}
}
}
function permuteChar(sChar, sSource) {
var aCombos = [],
aMatchIndexes = [],
aPermutations = [],
aResults = [],
nMatches,
reMatch = new RegExp(sChar + '+', 'gi');
// Find matches
while (oMatch = reMatch.exec(sSource)) {
aMatchIndexes.push(oMatch.index);
}
nMatches = aMatchIndexes.length;
if (!nMatches) return;
// Generate combinations
aCombos.push(Array.apply(null, Array(nMatches)).map(function() {
return sChar;
}));
for (var i=0; i<nMatches; ++i) {
aCombos.push([]);
for (var j=0; j<nMatches; ++j) {
aCombos[aCombos.length-1].push((i<j)?sChar:sChar+sChar);
}
}
// Build list of permutations
for (var i=0; i<aCombos.length; ++i) {
heapsPermute(aCombos[i], aPermutations);
}
// Search and replace!
for (var i=0, j, a; i<aPermutations.length; ++i) {
a = aPermutations[i].split(' ');
j = 0;
aResults.push(sSource.replace(reMatch, function(sMatch) {
return sMatch.replace(reMatch, a[j++])
}));
}
return aResults;
}
console.log(permuteChar('x', 'ooxxooxoox'));
And then I saw melpomene's solution with a nice explanation, which is a lot more concise and elegant, so this is the accepted solution that I'm going with. For those still on ES5, here's my ES5 version of melpomene's function:
function charVariants(sChar, sSource) {
var aChunks = sSource.split(new RegExp(sChar + '+', 'i')),
aResults = [aChunks.shift()];
for (var i=0, a; i<aChunks.length; ++i) {
a = [];
for (var j=0; j<aResults.length; ++j) {
a.push(
aResults[j] + sChar + aChunks[i],
aResults[j] + sChar + sChar + aChunks[i]
);
}
aResults = a;
}
return aResults;
}
console.log(charVariants('x', 'ooxxooxoox'));
Thanks to all who spent time to help out.
Here's a possible solution:
function x_variants(str) {
const chunks = str.split(/x+/);
let results = [chunks.shift()];
for (const chunk of chunks) {
const acc = [];
for (const result of results) {
acc.push(
result + 'x' + chunk,
result + 'xx' + chunk
);
}
results = acc;
}
return results;
}
console.log(x_variants('ooxxooxoo'));
console.log(x_variants('ooxooxoox'));
The middle part is essentially a manual flatMap. If you have it, you could also do
results = results.flatMap(result => [result + 'x' + chunk, result + 'xx' + chunk]);
The algorithm works by first splitting the input string on any sequence of one or more contiguous x, turning e.g. 'AxBxC' into ['A', 'B', 'C'].
We then extract the first element and initialize an array of possible variants with it:
remaining input: ['B', 'C']
possible variants: ['A']
We then iterate over the remaining input elements and, for each element, add it twice to all possible variants (once with a separator of 'x', once with a separator of 'xx').
First 'B':
remaining inputs: ['C']
possible variants: ['A' + 'x' + 'B', 'A' + 'xx' + 'B']
= ['AxB', 'AxxB']
Then 'C':
remaining inputs: []
possible variants: [ 'AxB' + 'x' + 'C', 'AxB' + 'xx' + 'C'
, 'AxxB' + 'x' + 'C', 'AxxB' + 'xx' + 'C' ]
= [ 'AxBxC', 'AxBxxC'
, 'AxxBxC', 'AxxBxxC' ]
At every step the number of possible variants doubles.
When we run out of inputs, we return our complete list of variants.
I would consider making a simple recursive function that keeps track of where it is as it iterates through the string. Something like:
function doublex(str, index=0, strings = []){
for (let i = index; i < str.length; i++){
if (str[i] === 'x'){
let d = str.slice(0,i) + 'x' + str.slice(i)
strings.push(d)
doublex(d, i+2, strings)
}
}
return strings
}
// two x
console.log(doublex('ooxooxoo'))
// three x
console.log(doublex('ooxoxoxoo'))
I heard forEach require a function that get 3 parameter, what about style 4 where parameters defined it. Why it's can work?
let arr = ["A", "B", "C", "D"];
//1
function temp(value, index, arr) {
console.log(value);
}
arr.forEach(temp);
//2
arr.forEach(function(value, index, arr) {
console.log(value);
});
//3
arr.forEach((value, index, arr) => {
console.log(value);
});
//4
arr.forEach(e =>
{
console.log(e);
});
The function definition defines the names of some variables that any arguments will be passed to.
That is all.
It does not enforce the number of arguments that can be passed.
You can pass any number of arguments to any function.
Some arguments might be ignored.
function myFunction(a, b, c) {
console.log("My function with " + arguments.length + " arguments");
console.log(a, b, c);
for (var i = 0; i < arguments.length; i++) {
console.log("Argument " + i + " is " + arguments[i]);
}
}
myFunction(100);
myFunction(200, 300, 400, 500, 600, 700);
function myFunctionWhichChecks(a, b, c) {
if (arguments.length !== 3) {
throw new Error("myFunctionWhichChecks must have exactly 3 arguments");
}
console.log("My function which checks has " + arguments.length + " arguments");
}
myFunctionWhichChecks(800, 900, 1000);
myFunctionWhichChecks(800, 900, 1000, 1100);
function filter_list(l) {
var count = l.length;
console.log('the count is:', count);
function loop() {
for (var i = 0; i < count; i++) {
var type = (typeof l[i]);
if (type == 'string') {
l.splice(i, 1);
console.log('the list is', l);
filter_list(l);
} else {
console.log('this item is', l[i], 'the list is', l);
}
}
}
loop()
}
filter_list([1, 2, 'a', 'c', 'd']);
Essentially, it does get the job done, however for the final for loop, I am not sure why it runs through it 3 extra times? Would anyone be able to shed some light on this?
I know this isn't a direct answer to your question, but if all you need to do is filter strings out of an array, you could more easily do this with Array.prototype.filter():
[1, 2, 'a', 'c', 'd'].filter(function(i) { return typeof i !== 'string' });
JSFiddle
Or, if you want to keep it as a standalone function:
function filter_list(array) {
return array.filter(function(i) { return typeof i !== 'string' });
}