This is a trivial question but I am having hard time to convert ternary operator to if. Here is what I tried.
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
const result = (cache[stringifiedArgs] = !cache.hasOwnProperty(
stringifiedArgs
)
? fn(...args)
: cache[stringifiedArgs]);
return result;
};
}
// function memoize(fn) {
// const cache = {};
// return (...args) => {
// const stringifiedArgs = stringifyArgs(args);
// return result = (if (cache[stringifiedArgs] = !cache.hasOwnProperty(stringifiedArgs)) {
// fn(...args);
// } else {
// cache[stringifiedArgs];
// })
// };
// }
This is the cleanest I can get it--check the property and save the result of the memoized function in the cache if it doesn't exist. Then return it from the cache.
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
if (!cache.hasOwnProperty(stringifiedArgs)) {
cache[stringifiedArgs] = fn(...args);
}
return cache[stringifiedArgs];
};
}
You could also use the in operator pretty safely here:
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = args.join(`,`); // just for testing
if (!(stringifiedArgs in cache)) {
cache[stringifiedArgs] = fn(...args);
}
return cache[stringifiedArgs];
};
}
const fib = memoize(n => n < 2 ? n : fib(n - 1) + fib(n - 2));
console.log(fib(78));
You probably need an iife if you want to maintain the same structure. However, this is not the cleanest way to do it...
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
const result = cache[stringifiedArgs] = (() => {
if (!cache.hasOwnProperty(stringifiedArgs)) {
return fn(...args);
} else {
return cache[stringifiedArgs];
}
})();
return result;
};
}
Related
I have such function and global variable (as array):
const arraysList = []
export const changeColorCategories = (array, draggedColumnId) => {
const isColor = arraysList.length ? arraysList[0][0]?.color : [];
if (typeof isColor === 'string') {
firstLevelColor = isColor;
}
return array.map((item, index, categories) => {
item.color = draggedColumnId !== 3 ? '#010172' : '#000000';
arraysList.push(categories);
if (firstLevelColor && !draggedColumnId) {
item.color = firstLevelColor;
}
if (item?.children?.length) {
changeColorCategories(item.children);
}
return item;
})
}
Every call of this function push some data to array. In this function I use recursion. So how i can clear this array only when this function will end it's work.
You can call the recursion function inside another function this way you can run anything you want when the function ends
const arraysList = []
export const changeColorCategories = (array, draggedColumnId) => {
const isColor = arraysList.length ? arraysList[0][0]?.color : [];
if (typeof isColor === 'string') {
firstLevelColor = isColor;
}
return array.map((item, index, categories) => {
item.color = draggedColumnId !== 3 ? '#010172' : '#000000';
arraysList.push(categories);
if (firstLevelColor && !draggedColumnId) {
item.color = firstLevelColor;
}
if (item?.children?.length) {
changeColorCategories(item.children);
}
return item;
})
}
function runRucFunc(){
const result = changeColorCategories();
//Your other code goes here
return result;
}
You can just put your recursion part inside a sub function.
Below I've called the inner function inner, I've also moved the arrayList into the function, due to closures you wound't even need to clear the arrayList, it would be cleared automatically as it goes out of scope.
eg.
export const changeColorCategories = (array, draggedColumnId) => {
const arraysList = []
function inner(array, draggedColumnId) {
const isColor = arraysList.length ? arraysList[0][0]?.color : [];
if (typeof isColor === 'string') {
firstLevelColor = isColor;
}
return array.map((item, index, categories) => {
item.color = draggedColumnId !== 3 ? '#010172' : '#000000';
arraysList.push(categories);
if (firstLevelColor && !draggedColumnId) {
item.color = firstLevelColor;
}
if (item?.children?.length) {
inner(item.children); //we call inner here instead.
}
return item;
})
}
// now call our inner
// you could do something even before your recursion.
const result = inner(array, draggedColumnId);
// here we can put what we want after recursion.
return result;
}
You could wrap the recursive call in another function like so:
const arr = []
const recursive = (counter = 0) => {
if(counter === 5)
return arr.map((v) => String.fromCodePoint(65 + v))
arr.push(counter)
return recursive(++counter)
}
const go = () => {
console.log(recursive()) // [A,B,C,D,E]
console.log(arr) // [0,1,2,3,4]
arr.length = 0 // clear the array
console.log(arr) // []
}
go()
Alternatively, if the global array does not actually need to be global, and is merely a container for working information of the recursive algorithm, then you could make it a parameter of the recursive function, which will then fall out of scope (and be garbage collected) when the recursion ends.
const recursive = (counter = 0, arr = []) => {
if(counter === 5)
return arr.map((v) => String.fromCodePoint(65 + v))
arr.push(counter)
return recursive(++counter, arr)
}
console.log(recursive()) // [A,B,C,D,E]
console.log(arr) // Error! Not in scope!
go()
Or, you could make the recursive function more intelligent and able to detect when it is processing the final recursion: how this is done will depend on the precise logic of the recursive function.
I am trying handle below code and its showing
enter image description here
const toArray = props =>
(props && props.split ? props.split(',') : props || []).map(item => item.trim());
const hasField = (entity, fields) => {
if (!fields.length) {
return false;
}
for (let i = 0; i < fields.length; i + 1) {
if (entity && entity.includes(fields[i])) {
return true;
}
}
return false;
};
module.exports = (entities, query) => {
const industries = toArray(query.industries);
const technologies = toArray(query.technologies);
const maturity = toArray(query.maturity);
return entities.filter(function (entity) {
const hasTecnology = hasField(entity.industries, industries);
const hasIndustury = hasField(entity.technologies, technologies);
const hasMaturity = hasField(entity.maturity, maturity);
const condition = hasTecnology || hasIndustury || hasMaturity;
if (condition) return entity;
}, []);
};
output showing:
23:26 error Array.prototype.filter() expects a value to be returned at the end of function
array-callback-return
Line 23:26 is ==> module.exports = (entities, query) => {
Could you please check this? What I wrongly doing here?
It's just as the error says - you're not always returning a value.
The callback return value only needs to be truthy or falsey. Change
if (condition) return entity;
to
return condition;
I have an exercise to make a function executeFunctions which takes as arguments a list of async functions and an argument, e.g. number.
The functions have to happen one after another, so if fun1 ends, fun2 needs to start with the value which was returned from fun1.
The problem is that I can't use async and await. I wanted to do it using reduce, but I guess that it wants to execute const res1 and go further before it returns a value (because of setTimeout).
Is there any way to do it without async and await?
const fun1 = function(value) {
return setTimeout(() => value*2, 3000)
}
const fun2 = function(value) {
return setTimeout(() => value*4, 3000)
}
const cb2 = (value) => {
return value*10
}
const executeFunctions = (funTab, cb) => (n) => {
const res1= funTab[0](n)
console.log(res1)
const resReduce = funTab.reduce((prev,curr) => {
const res2 = curr(prev)
return prev+res2
}, res1)
return cb(resReduce)
};
executeFunctions([fun1,fun2], cb2)(2)
We can use Promise-chaining:
const fun1 = function(value) {
return Promise.resolve(value * 2);
}
const fun2 = function(value) {
return Promise.resolve(value * 2);
}
const fun3 = function(value) {
return Promise.resolve(value * 2);
}
const executeFunctions = (funcList) => (n) => {
let chain = Promise.resolve(n); // initial value
for (let i = 0; i < funcList.length; i++) {
chain = chain.then(funcList[i]); // keep chaining
}
return chain; // last promise
};
const main = () => {
// we need to wait for the last promise in order to print the result
executeFunctions([fun1, fun2, fun3])(2).then(x => console.log('solution is:', x));
}
main() // prints: "solution is: 16"
or, we can also use a modified version of the suggested reduce solution, by changing the implementation of executeFunctions as follows (the rest of the code should remain as in the previous snippet):
const executeFunctions = (funcList) => (n) => {
const init = Promise.resolve(n);
const res = funcList.reduce((p, c) => {
return p.then(c)
}, init);
return res;
};
I have function like below.
If the value of the filter is an array with more than 4 I want to return just the key.
For instance const result = gethitedShips(); // result be 1 or 2 but I get undefined
I totally got confused where to return what
getHitShips = () => {
const { players } = this.props;
return Object.keys(players).forEach(key => {
const hitShips = players[key].ships.filter(ship => ship.health <= 0);
if (hitShips.length >= 5) return key;
return null;
});
};
You could filter the keys by checking the length
const getHitedShips = () => {
const { players } = this.props;
return Object
.keys(players)
.filter(key => players[key].ships.filter(ship => ship.health <= 0).length >= 5);
};
I have some code that is working but I want to abstract it into a functional component I can use elsewhere in my script. I am getting an undefined error:
This works:
//add an index to each element
var items = learning_check.map(function(el,i) {
var o = Object.assign({}, el);
o.key = i;
return o;
});
this doesn't:
const addIndex = (a) => {
console.log('addIndex initiated')
a.map = (el,i) => {
var o = Object.assign({}, el);
o.key = i;
return o;
}
}
called with
const mItems = addIndex(learning_check); // initiated
console.log('mItems: ' + mItems); // undefined
Firstly, I'd like to say that you're on the right track. You're missing two things.
You need to call map and not reassign it, like a.map(...) and not a.map = .... And, you need to return the result of map from your addIndex function. Like so,
const addIndex = (a) => {
console.log('addIndex initiated');
// Notice the return
return a.map((el, i) => { // See how we call map here
var o = Object.assign({}, el);
o.key = i;
return o;
});
}
// Mock
const learning_check = [{
id: "abcde"
}, {
id: "fghij"
}];
const mItems = addIndex(learning_check); // initiated
console.log('mItems: ' + JSON.stringify(mItems));
I'll suggest a simplification to your code here, you could use it if you like
const addIndex = (a) => {
console.log('addIndex initiated')
return a.map((el, i) => Object.assign({
key: i
}, el));
}
// Mock
const learning_check = [{
id: "abcde"
}, {
id: "fghij"
}];
const mItems = addIndex(learning_check); // initiated
console.log('mItems: ' + JSON.stringify(mItems));
Two bugs in your code
1) You are not returning anything from the function.
2) You are not calling the map function.
const addIndex = (a) => {
console.log('addIndex initiated')
return a.map((el, i) => {
var o = Object.assign({}, el);
o.key = i;
return o;
})
}