I have a callback function:
function map(item, callback) =>
Object.fromEntries(
Object.entries(item).map(callback)
)
const replaceDollarCb = ([key, value]) => [key.replace('%$%', '$'), typeof value === 'object' && value !== null && !Array.isArray(value) ? replaceDollarCb(value) : value]; // Here I get "undefined is not a function".
UtilObject.map(subQuery, replaceDollarCb);
It keeps failing to find the function itself (replaceDollarCb). I've used this and even changed them to non-arrow functions.
It's not that the method is undefined within itself, it's that you're not passing the expected array of key & value as arguments.
You'll need to recall your method with map not directly replaceDollarCb to make it work as I think you expected.
const map = (item, callback) =>
Object.fromEntries(
Object.entries(item).map(callback)
)
const replaceDollarCb = ([key, value]) => [key.replace('%$%', '$'), typeof value === 'object' && value !== null && !Array.isArray(value) ?
map(value, replaceDollarCb) :
value
];
const subQuery = {
"foo%$%": {
"subfoo%$%": "bar"
}
}
console.log(map(subQuery, replaceDollarCb));
Hi :) I'm not sure I understand your question, but map is reserved word in JavaScript as map function - thank you, Quentin, on arrays - exists and defining/overriding it (I'm not sure what's first lines meant to do) is bad idea.
Next problem is that you use replaceDollarCb before defining it. Did you mean recursion?
EDIT:
I'm also not sure why you "define" map first and use UtilObject.map too. Maybe that's something that could help you :)
Related
Here, I am new to JavaScript. I am solving questions; however, I am having a problem understanding chaining more than one method together. I have been trying to understand this solution, but it took me a lot of time, and I still don't get it.
I understand that I will input the array that I needed to change according to the specific function, which I opted. I understand all of methods functions, but I don't understand their syntax here, so can someone please explain each step to me ?
const group_By = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
In as few words as possible.
Firstly they compute a ternary expression, here they are checking if the input is a function, if it is they pass it as is, otherwise they create an anonymous function that tries to access the given property. The arrow function after the colon can seem a little confusing but it's still just a function. It takes one argument called val, and returns property which key is inside the fn variable.
typeof fn === 'function' ? fn : val => val[fn]
The next step is to create a new array with new values for each of the elements. Output of this step is just a list of values to group elements on.
For instance calling it on array ["a", "bb"] with a fn='length' would return [1,2]
arr.map(typeof fn === 'function' ? fn : val => val[fn])
Then they call the .reduce function on the output array. The purpose of the reduce function is to create a single value out of all the elements slowly iterating over it. You can tell that the last step returns accumulator value back, and that it is passed as a first argument to the function called on the next element. The empty object at the end is just an initial value of the accumulator.
.reduce((acc, val, i) => {
...
return acc;
}, {});
And finally for the step that does the accumulation. Here firstly the val from the result of the map, is used to access property of the newly created object. If the value does not exist it replaced with an empty array || []. That has the element of the initial array at the same index concatenated onto it. If there were some elements it just adds new ones to it and reassigns the value.
acc[val] = (acc[val] || []).concat(arr[i]);
Okay, what I understood from your query is that you are trying to chain multiple functions together.
function Chained() {
// this reference.
const _this_ = this
this.Function1 = () => // do something and return _this_
this.Function2 = () => // do something here and return _this_
}
Above you can see that chain is a simple object which returns "this" as context. and on context, we already have Function1 and Function2. so due to this following will be valid.
const _ExecuteChained = new Chained()
// Now you can run _ExecuteChained.Function1().Function2() and so on.
Now coming to your code.
const group_By = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val,
i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
Here you are just running a loop on arr and validating if the second param is a function or not if function then return it as is (Since you are using a map it will be stored at the given index. else just get the value of the function at the given key and return it.
Reduce.
in Reduce you are trying to accumulate a given value with (contact or merge or extend) value at a given index of arr in this case function.
I was working on a coding problem and I came across something that's throwing me for a loop(no pun intended). It's fairly simple, but I'm hoping for clarity from someone with more experience.
I was trying to solve it as such, but it wasn't working (I know it isn't necessary to check for zero, but I was just messing around and found this "quirk")
const filter_list = (l) => {
return l.filter(item => {
if(typeof item === 'number' || item === 0) {
return item;
}
})
}
It wasn't passing the tests, but when it's written like this, it passes all the tests:
const filter_list = (l) => l.filter(item => typeof item === 'number' || item === 0);
What is it about the second version that makes it pass the tests? There's a syntax difference, but the logic seems like it's the same to me.
The logic isn't the same. In the first version you have return item;, you don't return item in the second version. The second version returns the condition result.
The second version is equivalent to this:
const filter_list = (l) => {
return l.filter(item => {
return typeof item === 'number' || item === 0;
})
}
And if you want to abbreviate the first function, it would be:
const filter_list = (l) => l.filter(item => typeof item === 'number' || item === 0 ? item : undefined);
Your condition logic also doesn't make much sense. It will be true for all numbers, so adding || item === 0 won't change the result. I suspect you meant &&. But since you're using strict equality, there's no need to test the type -- nothing but a number can be strictly equal to 0.
I am calling some functions where I end up passing so many arguments it is getting silly! Is this some type of code smell and suggests I am doing things incorrectly? Is there a better way of structuring things?
Example:
checkMyData(
string1,
string2,
string3,
string4,
string5,
string6,
string7,
string8,
string9,
arrayData1,
arrayData2,
arrayData3,
arrayData4,
arrayData5,
arrayData6,
arrayData7,
arrayData8,
arrayData9
);
Why not
checkMyData(
stringArgs,
arrayArgs
);
and pass them as arrays?
Other option:
function checkMyData(...args) {
const stringArgs = args.filter(x => typeof x === 'string')
const nonStringArgs = args.filter(x => typeof x !== 'string')
console.log(stringArgs)
console.log(nonStringArgs)
}
checkMyData('a','b','c',[1,2,3],[4,5,6])
I have a method which returns a value from an element in the array. Not all the elements have the property I want to return. I would like to do this function with one line using the method find(). I've tried this way to solve it:
getExecsFromTour(tourId){
return this.repInfo.find(el => el.id == tourId ).execs || [];
}
But the elements which don't contain the property execs return an error of undefined.
To solve it, I had to store the result in a local variable:
getExecsFromTour(tourId){
let items = this.repInfo.find(el => el.id == tourId);
return items != undefined ? items.execs : [];
}
But I would like to know if I am missing something and this function can be achieved with one sentence.
You seem to have the general idea, Array.prototype.find will search the array for the first element which, when used as an argument of the callback, will have the callback return a truthy value. If nothing is found, it returns undefined.
Your code should work, but yes, one way to do it in one line (if you want) is to use:
getExecsFromTour(tourId){
return (this.repInfo.find(el => el.id == tourId) || {}).execs || [];
}
If Array.prototype.find returns undefined, the first inner parenthetical expression will be evaluated to empty object, which can attempt (and fail) to access the .execs key without a TypeError, which will also evaluate to undefined, in which case the function returns empty array, which is what your code above does.
EDIT: Someone commented this solution already, lol, but as the comments say, nothing wrong with keeping it multiline (more readable that way).
what about
getExecsFromTour(tourId){
return this.repInfo.find(el => 'execs' in el && el.id == tourId ).execs || [];
}
...
EDITED
var a = [{execs : 1, id:4}, {id:5}];
function getExecsFromTour(tourId, x){
return (x = a.find(el => 'execs' in el && el.id == tourId )) ? x.execs : [];
}
this time at least I ran it couple of times
Many times I ask myself the same question... With all that syntaxes (not always intuitive) to write quite direct code in JS, I was wondering, would someone know about a one-liner for that kind of operation?
var setFeatured = entry => {
entry.isFeatured = true;
return entry
}
SomeCallThatReturnsAPromise.then(entries => entries.map(setFeatured))
To assign a property and return the object in one shot, that I could put in a readable way directly as arg of entries.map
To give a feedback about what was proposed to me, the common answer was to return a result with a OR operator, after an assignation or function call (which returns undefined, null, false, never, well anything that will trigger the part after the OR):
return entry.isFeatured = true || entry
The interest of my question was to know if I could take advantage of a more compact syntax:
SomeCallThatReturnsAPromise()
.then((entries:EntryType[]) => entries
.map(entry => entry.isFeatured = true || entry)
.filter(entry => entry.something == true))
.then((entries:EntryType[]) => someCallThatReturnsNothingButHasToBeDoneThere() || entries)
.then((entries:EntryType[]) => console.log(entries))
would be easier to read than:
SomeCallThatReturnsAPromise
.then((entries:EntryType[]) => entries
.map(entry => {
entry.isFeatured = true;
return entry;
})
.filter(entry => entry.something == true))
.then((entries:EntryType[]) => {
someCallThatReturnsNothingButHasToBeDoneThere();
return entries;
})
.then((entries:EntryType[]) => console.log(entries))
Notes:
1) I try to avoid creating a function for that. My question was motivated by curiosity and just concerns what Vanilla ES6 or 7 syntaxes have to offer.
2) I was answered to use .forEach rather than .map. I design my code with a functional approach (hence the importance of compact callbacks), so .forEachis not necessarily a good choice for me (and apparently it doesn't have advantages over map in terms of performance or memory consumption). A one-line syntax is convenient both when handling promises callbacks or chains of array functions...
3) the returned type when using the OR operator is a union type, EntryType|null. So it breaks the typing for the subsequent calls and implies a type assertion:
SomeCallThatReturnsAPromise()
.then((entries:EntryType[]) => entries
.map(entry => (entry.isFeatured = true || entry) as EntryType)
.filter(entry => entry.something == true))
.then((entries:EntryType[]) => (someCallThatReturnsNothingButHasToBeDoneThere() || entries) as EntryType[])
.then((entries:EntryType[]) => console.log(entries))
That's getting heavier... I still don't know if I'll use that or stick with the two lines including the return statement.
4) That's a reduced example. I know that my first then contains a synchronous call or that my example could be more accurate.
entries.forEach( (entry) => entry.isFeatured = true );
No need to define the function separately.
Furthermore, as your elements are objects and are handled by reference, one can replace map() by forEach(), which removes the necessity to return a value.
(using map() you would end up with two arrays consisting of the same elements, which probably is not, what you need)
You can do what #Sirko wrote but return it like so:
SomeCallThatReturnsAPromise.then(entries => entries.forEach(entry => entry.isFeatured = true) || entries)
There's no need to use map, instead using forEach will give you a "one-liner", but then you want to return the same value that you received, using logical or (||) you can do that.
although #Sirko is right and, in that specific case, forEach has more sense than using map I think the OP was asking a generic question.
So, in general, how do you assign a property and then return the whole object? this is my suggestion:
function mutateObject(element, value) {
return (element.prop = value) && element || element
}
var object = {prop:1}
var returned = mutateObject(object, 2)
console.log(returned)
How does it work? the first part (element.prop = value) assigns the value to the property and return the value to the expression.
If the value returned is falsy, the value of the || clause is returned. If it's truthy the value of the && is returned.
In this case we return the element itself both times to be sure that's the object it will always be returned, no matter what we set in the property.
Another way to write that is (element.prop = value) ? element : element but, with this syntax, it looks more like a typo with the assignment instead of the comparison so I like the other syntax better.
//Example 1
const gimmeSmile = {}
console.log({ ...gimmeSmile, smile: ":)" })
// Example 2
const smiles = [{},{},{}]
.map(obj => ( { ...obj, smile: ":)"} ));
console.log(smiles)