What is the use of ,[] in an anonymous function called? - javascript

I was doing a coding challenge which takes in either a one or two dimensional array and then returns a flattened array. After writing my code I looked on the forums to see how others wrote theirs and found an interesting answer.
function flattenArray(array) {
return array.reduce((acc, cur) => acc.concat(cur), []);
}
Note at the end of the return line, he used ,[] after the concat. I tried to break it down to see if I could understand that last part but I am unable to throw {} around it without it throwing me an error.
function quickFlatten(array)
{
return array.reduce((acc, cur) => {
acc.concat(cur), [];
});
}
When this is called I am given a TypeError:
TypeError: acc.concat is not a function
What is ",[]" , how does it work and how can I learn more about what he did? It appears to make acc an array but only works when there are no {} in the anonymous function.

This is the initial value of the accumulator (called acc here) use by the reduce function.
Reduce builds up a value by iterating over an array and returning it for the next iteration. The initial value has to come from somewhere, and it comes as a second parameter of the reduce function :)
you should probably read this : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

Related

I'm confused about this statement, Object.entries

useEffect(() => {
cat &&
setFilteredProducts(
products.filter((item) =>
Object.entries(filters).every(([key, value]) =>
item[key].includes(value)
)
)
);
}, [products, cat, filters]);
I've been watching the video, over and over again but I can't seem to understand it properly, can somebody help me explain this line by line? I've get the point about "cat &&" but the rest confuses me.
Going through the above code line by line:
I am assuming you have a state variable with a setter function setFilteredProducts and two arrays products and filters, each having objects as values.
We are setting values in the state variable from the filtered values stored in the products variable.
Object.entries simply returns an array, where each item is an array with its first value as keys and the second value as the corresponding value, every is another function that applies on the array returned by the Object.entries function
The every function takes in a callback function as an argument, which tests whether all elements in the array pass the test implemented by the callback.
In this case, the test implemented is item[key].includes(value), which tests whether each iterated element(an object) in the products array has an array corresponding to key with value in it.
You can refer to
Object.entries here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
Array.prototype.every: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
Array.prototype.filter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Array.prototype.includes: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
you most your productlist.js check .i think there is a problem .when you have handleFilters check your value

I really don't understand this if with NOT! operator

firstly here is my code :
const removeFromArray = function (...args) {
const array = args[0];
const newArray = [];
array.forEach((item) => {
if (!args.includes(item)) {
newArray.push(item);
}
});
return newArray;
The problem is this !args.includes(item), the NOT operator, it really makes no sense in my mind in this case... I tried to reformulate, rewrite but it doesn't help.
The function is supposed to push every element into the array unless it is included in the function arguments (for example with arguments like this : removeFromArray([1, 2, 3], 2, 4)) but how the 'unless' work with this if condition ?
Can you light up my lantern please ?
It seems you kind of interpreting the "unless" as literal here and I see how this might be a little bit confusing at first.
Perhaps if it was rephrased, it might be less confusing:
don't push element into array unless it's NOT including in the arguments.
Or more literal to actual code:
if item is NOT in the arguments, add it to the array
.includes() returns true or false and ! negates the result. The loop will only execute if .includes() in your example returns false.
To me it seems as if you want to filter the array, so maybe you should use the .filter() method:
const newArray = array.filter((el)=>!(testArray.includes(el)))

Reduce function returning assignment is throwing error (ESLint issue: no-return-assign)

My code (which works):
const calculateBalance = (coins) => {
console.log('coins', coins);
return coins.reduce((bal, coin) => (bal += parseInt(coin.balance)), 0);
};
Basically I just want to add up all the coin balances in my portfolio, however I'm getting an eslint error.
Arrow function should not return assignment.
Googling I found this: https://eslint.org/docs/rules/no-return-assign
One of the interesting, and sometimes confusing, aspects of JavaScript is that assignment can happen at almost any point. Because of this, an errant equals sign can end up causing assignment when the true intent was to do a comparison. This is especially true when using a return statement.
Here they have an example of what to do:
function doSomething() {
return (foo = bar + 2);
}
However that is what I implemented, but eslint is still complaining... is there a way to update my code block above to make it pass?
From the specs. (here MDN)
The reduce() method applies a function against an accumulator and each
element in the array (from left to right) to reduce it to a single
value.
As your bal is your accumulator, simply do bal + parseInt(coin.balance)

How to retrieve the first item in an array in javascript?

I am new to javascript. I am doing a task which trying to get the first item removed from an array in javascript.
Method One
function getFirst(arr, item) {
arr.push(item);
var removed = arr.shift();
return removed;
}
Method Two
function getFirst2(arr, item) {
arr = arr.push(item);
var removed = arr.shift();
return removed;
}
I comes out with these two solution but only method one accepted and method two is the wrong one which return Uncaught TypeError: arr.shift is not a function().
What is the extacly meaning of Uncaught TypeError and state that arr.shift is not a function but it works on Method one?
Any help will be appreciate! Thanks!
Your function getFirst2() is not working because of arr = arr.push(item).
Here arr actually becomes a number, as the push method on an array returns the new length property of the object upon which the method was called.
Thus calling method push on a number throws a TypeError.
Your first Method is alright. But i'd like to note that you do not always have to create a local fucntion-scope variables. Your return statement can return computed values. So instead of
function getFirst(arr, item) {
arr.push(item);
var removed = arr.shift();
return removed;
}
I would go for
function getFirst(arr, item) {
arr.push(item);
return arr.shift();
}
You can apply the shift function on an array. In method 2, arr is not an array anymore because I think that the push method returns the length of the array. This is why you are getting a typeError.
Try printing arr before applying the shift method to see what it is.
Javascript has many inbuilt functions that are attached to different data types. The Array type has the functions push(), unshift(), shift() etc that are attached to every array but not to other non-array types.
When you use these Array functions on any type that is not an array you get the Uncaught type error, because the Javascript interpreter cannot read the function off that type.
Your second function on this line: arr = arr.push(item); , changes the value of arr to a number because the return value of the function arr.push(item); is a number(Int). Hence trying to call .shift() on arr is no longer allowed because arr is no longer an array.

Recursive JavaScript function is losing the return value

I want to search a string in a nested JSON object. If the string found in an object, I need to return that object.
I am using a recursive function to achieve this. The problem is, the function is recursing until the end and not returning the object found.
Please see the entire code in jsfiddle
function search(obj, name) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
return obj; //NOT RETURNING HERE
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
//console.log(ch);
ch.forEach(function(val) {
search(val, name)
});
}
return -1;
}
search(myJson, "VM10-Proc4")
I am not sure what is going wrong.
You need to stop looping over children when it finds one that matches.
function search(obj, name) {
console.log(obj.name, ",", name, obj.name == name);
if (obj.name == name) {
return obj;
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
for (var i = 0; i < ch.length; i++) {
var found = search(ch[i], name);
if (found) {
return found;
}
}
}
return false;
}
FIDDLE demo
The correct return value is getting lost in the chain of recursive function calls. After the correct value is found, any additional searches made will return incorrect values from that point on.
A couple ways to handle this:
1. Cancel the search
When the correct value is found, immediately return it all the way up the recursive stack, without searching any more of the current arrays or the nested arrays. In other words, cancel the rest of the search.
#Barmer's answer is an example of this. The key part of his code is the use of for loops rather than the each method to iterate through the arrays, since it's much easier to interrupt a for loop.
2. Store the value somewhere safe
When the correct value is found, store it somewhere safe, allow the rest of the search to continue, and after the initial function call has finished access the value. The simplest way is to store the correct value in a global variable, though that's not a good practice as it violates the encapsulation of the function.
#shyam's answer presents a cleaner solution: Passing a reference to a global variable as a function parameter, setting the parameter when the correct value is found, and then accessing the global variable after the initial function call has finished.
Choosing between the two
In laymen's terms, the intended logic of the function could be summed up as follows: When you find what you're looking for, stop, and let me know what it is immediately. The only reason to continue searching would be if multiple pieces of data needed to be found. I'm assuming that's not the case here.
Of the two approaches, #2 is a quick-fix workaround that should work fine but will further confuse anyone who's trying to understand the intended logic of the function. Why is the search continuing if it's only looking for a single piece of data that's already been found?
#1 is a refactoring of the function so that it behaves more consistently with the intended logic, which would make the function easier to understand. The function stops searching when it finds what it needs.
I know this is an old post, but I can see 2 issues with this:
1) the recursive call isn't returning the result up the call stack i.e.
search(val, name)
Should be
return search(val, name)
2) it looks like you are using array.forEach(). The documentation states:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool. Use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can use every() or some() instead. If available, the new methods find() or findIndex() can be used for early termination upon true predicates as well.
What this means is, effectively, when you find the result you are looking for you want to send it back up the call stack. Using array.forEach will continue to recursively look through the hierarchy and return all values, not just the one you are interested in. Therefore the last returned value maybe one you don't expect, like undefined! Therefore use a different method of iterating i.e.
for (var i = 0; i < ch.length; i++) {
var val = ch[i];
return search(val, name, ret);
}
The accepted answer does spoon feed you part of this answer but doesn't explain why. Hence this answer
Since you are recursing the return might be nested too deep for you to get a meaningful result. Instead you can try passing an extra argument to collect the results.
function search(obj, name, ret) {
console.log(obj["name"], ",", name, obj["name"] == name);
if (obj["name"] == name) {
ret.push(obj);
return
}
if (obj.children || obj._children) {
var ch = obj.children || obj._children;
ch.forEach(function(val) {
search(val, name, ret);
});
}
}
var result = [];
search(myJson, "VM10-Proc4", result)
Here is a solution using object-scan
// const objectScan = require('object-scan');
const myJson = {"name":"UCS - San Jose","type":"Minor","children":[{"name":"VM1","type":"Clear","children":[{"name":"VM1-Proc1","type":"Clear","children":[{"name":"VM1-Proc1-child1","type":"Clear"}]},{"name":"VM1-Proc2","type":"Clear"},{"name":"VM1-Proc3","type":"Clear"},{"name":"VM1-Proc4","type":"Clear"},{"name":"VM1-Proc5","type":"Clear"},{"name":"VM1-Proc6","type":"Clear"},{"name":"VM1-Proc7","type":"Clear"},{"name":"VM1-Proc8","type":"Clear"},{"name":"VM1-Proc9","type":"Clear"},{"name":"VM1-Proc10","type":"Clear"}]},{"name":"VM2","type":"Clear","children":[{"name":"VM2-Proc1","type":"Clear"},{"name":"VM2-Proc2","type":"Clear"},{"name":"VM2-Proc3","type":"Clear"},{"name":"VM2-Proc4","type":"Clear"},{"name":"VM2-Proc5","type":"Clear"},{"name":"VM2-Proc6","type":"Clear"},{"name":"VM2-Proc7","type":"Clear"},{"name":"VM2-Proc8","type":"Clear"},{"name":"VM2-Proc9","type":"Clear"},{"name":"VM2-Proc10","type":"Clear"}]},{"name":"VM3","type":"Clear","children":[{"name":"VM3-Proc1","type":"Clear"},{"name":"VM3-Proc2","type":"Clear"},{"name":"VM3-Proc3","type":"Clear"},{"name":"VM3-Proc4","type":"Clear"},{"name":"VM3-Proc5","type":"Clear"},{"name":"VM3-Proc6","type":"Clear"},{"name":"VM3-Proc7","type":"Clear"},{"name":"VM3-Proc8","type":"Clear"},{"name":"VM3-Proc9","type":"Clear"},{"name":"VM3-Proc10","type":"Clear"}]},{"name":"VM4","type":"Minor","children":[{"name":"VM4-Proc1","type":"Clear"},{"name":"VM4-Proc2","type":"Clear"},{"name":"VM4-Proc3","type":"Minor"},{"name":"VM4-Proc4","type":"Clear"},{"name":"VM4-Proc5","type":"Clear"},{"name":"VM4-Proc6","type":"Minor"},{"name":"VM4-Proc7","type":"Clear"},{"name":"VM4-Proc8","type":"Clear"},{"name":"VM4-Proc9","type":"Clear"},{"name":"VM4-Proc10","type":"Clear"}]},{"name":"VM5","type":"Clear","children":[{"name":"VM5-Proc1","type":"Clear"},{"name":"VM5-Proc2","type":"Clear"},{"name":"VM5-Proc3","type":"Clear"},{"name":"VM5-Proc4","type":"Clear"},{"name":"VM5-Proc5","type":"Clear"},{"name":"VM5-Proc6","type":"Clear"},{"name":"VM5-Proc7","type":"Clear"},{"name":"VM5-Proc8","type":"Clear"},{"name":"VM5-Proc9","type":"Clear"},{"name":"VM5-Proc10","type":"Clear"}]},{"name":"VM6","type":"Minor","children":[{"name":"VM6-Proc1","type":"Clear"},{"name":"VM6-Proc2","type":"Clear"},{"name":"VM6-Proc3","type":"Minor"},{"name":"VM6-Proc4","type":"Clear"},{"name":"VM6-Proc5","type":"Clear"},{"name":"VM6-Proc6","type":"Clear"},{"name":"VM6-Proc7","type":"Minor"},{"name":"VM6-Proc8","type":"Clear"},{"name":"VM6-Proc9","type":"Clear"},{"name":"VM6-Proc10","type":"Clear"}]},{"name":"VM7","type":"Clear","children":[{"name":"VM7-Proc1","type":"Clear"},{"name":"VM7-Proc2","type":"Clear"},{"name":"VM7-Proc3","type":"Clear"},{"name":"VM7-Proc4","type":"Clear"},{"name":"VM7-Proc5","type":"Clear"},{"name":"VM7-Proc6","type":"Clear"},{"name":"VM7-Proc7","type":"Clear"},{"name":"VM7-Proc8","type":"Clear"},{"name":"VM7-Proc9","type":"Clear"},{"name":"VM7-Proc10","type":"Clear"}]},{"name":"VM8","type":"Clear","children":[{"name":"VM8-Proc1","type":"Clear"},{"name":"VM8-Proc2","type":"Clear"},{"name":"VM8-Proc3","type":"Clear"},{"name":"VM8-Proc4","type":"Clear"},{"name":"VM8-Proc5","type":"Clear"},{"name":"VM8-Proc6","type":"Clear"},{"name":"VM8-Proc7","type":"Clear"},{"name":"VM8-Proc8","type":"Clear"},{"name":"VM8-Proc9","type":"Clear"},{"name":"VM8-Proc10","type":"Clear"}]},{"name":"VM9","type":"Clear","children":[{"name":"VM9-Proc1","type":"Clear"},{"name":"VM9-Proc2","type":"Clear"},{"name":"VM9-Proc3","type":"Clear"},{"name":"VM9-Proc4","type":"Clear"},{"name":"VM9-Proc5","type":"Clear"},{"name":"VM9-Proc6","type":"Clear"},{"name":"VM9-Proc7","type":"Clear"},{"name":"VM9-Proc8","type":"Clear"},{"name":"VM9-Proc9","type":"Clear"},{"name":"VM9-Proc10","type":"Clear"}]},{"name":"VM10","type":"Clear","children":[{"name":"VM10-Proc1","type":"Clear"},{"name":"VM10-Proc2","type":"Clear"},{"name":"VM10-Proc3","type":"Clear"},{"name":"VM10-Proc4","type":"Clear"},{"name":"VM10-Proc5","type":"Clear"},{"name":"VM10-Proc6","type":"Clear"},{"name":"VM10-Proc7","type":"Clear"},{"name":"VM10-Proc8","type":"Clear"},{"name":"VM10-Proc9","type":"Clear"},{"name":"VM10-Proc10","type":"Clear"}]}]};
const search = (obj, name) => objectScan(['**.name'], {
rtn: 'parent',
abort: true,
filterFn: ({ value }) => value === name
})(obj);
console.log(search(myJson, 'VM10-Proc4'));
// => { name: 'VM10-Proc4', type: 'Clear' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan

Categories

Resources