Array that is consoled.log is not updating javascript - javascript

My array numbers are not updating when they are squared. I'm not familiar with callbacks and how to get their values to update the array. The foreach function runs the callback on each element of the array (updates the array passed in). forEach does not return anything.
//This function is to square a desired number
const square = a => (a*a)
//this function
function map(array, callback) {
const arrNew= [];
for (let i = 0; i < array.length; i++) {
arrNew.push(callback(array[i]));
}
return arrNew;
}
function forEach(array, callback) {
let newArray = [];
for (let i = 0; i < array.length; i+=1) {
callback(array[i]);
newArray.push(callback(array[i]));
}
}
var myarray = [10,20];
forEach(myarray, square);
// this should log 100,400 but is instead doing 10,20
console.log(myarray);

You need to return the newArray in forEach
//This function is to square a desired number
const square = a => (a*a)
function forEach(array, callback) {
let newArray = [];
for (let i = 0; i < array.length; i+=1) {
newArray.push(callback(array[i]));
}
return newArray
}
var myarray = [10,20];
myarray = forEach(myarray, square);
// this should log 100,400 but is instead doing 10,20
console.log(myarray);

For this example you can use the below code.
const myArray = [10, 20];
const squaredArray = myArray.map((item) => item * item);
console.log(squaredArray);
You can use map when do you want access de all items in your array and return one value. The "forEach" you access also your array, but the "forEach" can't return any value.

I think you might be over complicating this process. To get your desired result you can simply use the map function. For example:
var myarray = [10,20]
console.log(myarray.map((number) => number * number))
If you run this code you will get [100,400] logged in the console.
What is happening here is that we are calling the map method on the array. This method is taking a callback function. The callback function is this part
(number) => number * number)
So what is happening here? The map method is iterating over the provided array, and for each element, it is running that function, then returns the results in a new array.
I would suggest watching some videos and reading more about higher-order functions (which .map is one example of)
This video helped me alot when I was first learning about them
.

Related

Conditional response in a map chained to a filter that may return an empty array

I have filter and map function chained. I need to do something conditional on whether a filter returns an empty array or not. However the map function on the array does not seem to be invoked if the filter returns an empty array.
const letters = ["a", "b", "c"];
const numbers = [1, 2, 3]
function result (arr) {
arr.filter((x) => {return x === "a"}).map((y, i, arr) => {
if(arr.length === 0) {
return //do something
} else {
return //do something else
}})
}
Is this expected or am I doing something wrong?
I was expecting the filter result to be passed to the map function, which can be used as the 3rd argument of the map function: map(item, index, array)
Here's a JSFiddle of the problem
https://jsfiddle.net/sub3z0xh/
You’re right about what’s happening. Array methods run once per element in the source array. If the source array is empty, it doesn’t run.
This isn’t new or working different with array methods vs a basic for loop. Example:
const arr = [];
for (let i = 0; i < arr.length; i++) {
console.log(“this code never runs because there are no elements to loop”);
}
So maybe just store the result of the filter in a variable instead. Get rid of the chained map since it may not run. Check the size/contents of your filtered array, then do stuff with that.

why isn't recursion working? i am trying to display n to 1 series

Javascript Recursion
why isn't recursion working here? i see coundown(n-1); isn't working for some reason. I want to display [5,4,3,2,1]
function countdown(n){
if (n<1){
return [];
} else {
var myArr = [];
myArr.push(n);
countdown(n-1);
return myArr;
}
}
countdown(5);
Your code creates a new array at every recursive call, puts one value in it and returns it. Nothing is done with the array that is returned, as each execution instance of your function seems only interested in its own array, which it returns.
You need to create one array, and extend that while backtracking out of recursion, each time making sure you capture the array that the recursive call gives you back as return value:
function countdown(n) {
if (n < 1) {
// This is the only time you should create an array:
return [];
} else {
// Get the array that comes out of recursion!
let myArr = countdown(n-1);
// Prefix the current value into it
myArr.unshift(n);
// And pass that extended array further up
// the recursion tree:
return myArr;
}
}
console.log(countdown(5));
Written a bit more concise it could become:
const countdown = (n) => n < 1 ? [] : [n].concat(countdown(n-1));
console.log(countdown(5));
And without recursion:
const countdown = (n) => Array.from({length: n}, (_, i) => n - i);
console.log(countdown(5));
var myArr =[];
function clearandcountdown(n)
{
myArr = []; // clearing the array each time when the function called
return countdown(n); // calling the recursion function
}
function countdown(n){
if (n<1)
{
return []
}
else
{
myArr.push(n);
countdown(n-1);
}
return myArr;
}
document.write(clearandcountdown(5));
You must use this code here you created myArr inside the else statement and you are setting it to empty for every function call here I used one extra function to clear the array each time when you call the function. Hope this will clear your doubts. Thank You :)

Javascript how do i get my function array to give me more then the first value

function countUniqueItems(arr) {
nums = [];
for (i = 0; i < arguments.length; i++) {
const item = arr[i];
console.log(i);
//console.log(item);
if (nums.includes(arr) === true) {
//console.log('8 is in the array');
//nums.push(arr)
} else {
nums.push(arr);
//console.log('8 is NOT in the array');
//nums.push(item)
}
}
return nums;
}
countUniqueItems(1, 2);
So it will give back the first argument which is 1 but i want it to be able to say argument 2 and 3 and so on
So you need to pass an array into the function, in place of 1,2 pass [1,2].
Then inside your function, you should use arr.length in place of arguments.length.
Then you look at your logic for the loop, you are pushing atm arr into nums, but if you pass and array that isn't really want you want, you should be pushing item as that is the variable which represents your current element from the array.
It looks from you comments like you're trying to make a unique list of inputs. Perhaps something like this would do the trick.
EDIT: Updated to use arguments
function uniqueNumbers() {
let arrayOfArguments = [...arguments]
let uniqueNums = [];
arrayOfArguments.map(i => !uniqueNums.includes(i) ? uniqueNums.push(i) : null);
return uniqueNums;
};
console.log(uniqueNumbers(1,2,3,3));
you should either pass an array to countUniqueItems or use the arguments keyword in the for-loop.
Your code is only seeing 1 (as arr inside the function).
basic implementation to find unique items
function countUniqueItems(...arr) {
let nums = [];
for (let num of arr) {
if (nums.indexOf(num) === -1) nums.push(num);
}
return nums;
}
console.log(countUniqueItems(1, 2, 1));
Using Set you can remove the duplicate values, you dont need to do logic run the loop to find the unique values from array.
const a = [1,2,3,3];
const uniqueSet = new Set(a);
uniqueSet.size
let uniqueFinder = arr => { const uniqueSet = new Set(arr); return uniqueSet.size}
const arrywithduplicates = [1,2,3,3,4,4];
uniqueFinder(arrywithduplicates) // return 4
Read more about Set : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

Student trying to understand callback functions

Hi I'm trying to learn how to implement callback functions. My teacher has helped me out multiple times but I still can't pass data through the following equation below. I'm trying to get certain elements of array to get pushed into a new function if only they pass a test within the function. Please have a look and thank you for your input. An explanation as to why I get an empty array and resources to further my understanding would be appreciated.
// EACH DEFINITION
function each (collection, callback) {
for(var i = 0; i < collection.length; i ++){
callback(collection[i]);
}
}
// VARIABLE DECLARATION
var myArray = [1,2,3,4,5,6];
var isEven = function (num) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
test(item);
});
if(test(array)){
arr.push(array);
}
return arr;
}
// IMPLEMENT INVOCATION
implement(myArray, isEven);
You are building arr outside the each() loop.
I would think your code would be like this:
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
if(test(item)) {
arr.push(item);
}
});
return arr;
}
Though in this case there is no reason for your implement() filtering function at all, since javascript Array prototype already has a filter method. You could simplify your call to this:
var filteredArray = myArray.filter(isEven);
Though you might also then want to change your isEven definition to be more correct as:
var isEven = function (num, index, array) {
In your case you don't need to work with the last two parameters.
// EACH DEFINITION
function each (collection, callback, results) {
for(var i = 0; i < collection.length; i ++){
callback(collection[i]);
}
console.log(results);
}
// VARIABLE DECLARATION
var myArray = [1,2,3,4,5,6];
var isEven = function (num, array) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
function filter (item) {
if (test(item)) {
arr.push(item);
}
}
each(array, filter, arr);
// If you return arr here, it will still be empty. You must pass it to functions it is being operated on.
}
// IMPLEMENT INVOCATION
implement(myArray, isEven);
Not only are you trying to push to arr outside of your loop, but you're trying to return arr before it has gained any values.
Two points:
First, your implementation of callback functions is correct. As far as the concept of callbacks goes, you are calling and passing the functions correctly.
However, your implement() function probably has a bug. You are not pushing to arr until after each() has already been called:
function implement(array, test) { // array = myArray, test = isEven
var arr = [];
each(array, function(item) {
result = test(item);
});
// This block should be in the loop itself
// It should also refer to item, not array
if (test(array)) {
arr.push(array);
}
return arr;
}
Try this fix based on the code you provided:
// EACH DEFINITION
function each(collection, callback) {
for (var i = 0; i < collection.length; i++) {
callback(collection[i]);
}
}
// VARIABLE DECLARATION
var myArray = [1, 2, 3, 4, 5, 6];
var isEven = function(num) {
return num % 2 === 0;
};
// IMPLEMENT DEFINITION
function implement(array, test) { // array = myArray, test = isEven
var arr = [];
each(array, function(item) {
if (test(item)) {
arr.push(item)
}
});
if (test(array)) {
arr.push(array);
}
return arr;
}
// IMPLEMENT INVOCATION
var result = implement(myArray, isEven);
console.log(result); // For snippet results
Your callback, as you defined it, is
function(item){
test(item);
}
this will only call test on each item and that's it. Since you want to take it further and add item to arr if test returns true, you should put that checking code inside the callback as well, making it
function(item){
if (test(item)) {
arr.push(item);
}
}
so that this function will be called for each of the item.
Also, this part
if(test(array)){
arr.push(array);
}
is incorrect because you are passing a whole array into isEven when isEven is expecting a number. test(array) will always return false; that's why your arr is empty.
Modifying your code to work as you wanted, it would be
// IMPLEMENT DEFINITION
function implement(array, test){ // array = myArray, test = isEven
var arr = [];
each(array, function(item){
if (test(item)) {
arr.push(item);
}
});
return arr;
}
Resources wise, there are callbacks tutorial widely available online, as well as best practices. You can easily find one that suits you best by googling.
It looks to me like the entire issue here is in the implementation section you denote. All of the other code looks adequate.
each(array, function(item){
test(item);
});
Alright, first let's examine this piece of code. You are making a call to your each function, which will use the callback anonymous function defined here as shown.
However, if you were to look at the each function itself, there is no return (which means it returns undefined by default). There is also no modification being done in each. As a result, this set of code has no effect on the execution of the code, and from certain advanced compilation technique may actually be removed by the V8 engine in chrome if that was being used.
This means the only aspect of your code which is executing is
var arr = [];
if(test(array)){
arr.push(array);
}
return arr;
At this point, test is still the isEven function, so you are basically asking this
if(array % 2 === 0) arr.push(array);
Arrays in JavaScript behave interestingly when used in conditional statements, and in this situation the array essentially has toString called on it (more in depth here: https://stackoverflow.com/a/10556035/1026459 , but basically when you have object === number then it will attempt to use toPrimitive on the object which results in a string), which makes it
if("1,2,3" % 2 === 0)
which is false. As a result arr is unchanged, and returned in its original state of [].

forEach works - why not for loop?

I'm working on the flatten kata at codewars.com - my code closely resembles a solution I've found, so I feel like my logic is on the right track. But I can't seem to get my code to work and I don't know if it's a dumb syntax error or if I'm doing something fundamentally incorrect.
Instructions:
Write a function that flattens an Array of Array objects into a flat Array. Your function
must only do one level of flattening.
flatten([[1,2,3],["a","b","c"],[1,2,3]]) // => [1,2,3,"a","b","c",1,2,3]
Working solution using forEach:
var flatten = function (lol){
var res = [];
lol.forEach(function (x) {
if (x instanceof Array)
res = res.concat(x);
else
res.push(x);
});
return res;
}
My code using for loops:
var flatten = function (array){
var newArray = [];
for (i = 0; i < array.length; i++) {
if (i instanceof Array)
for (e = 0; e < i.length; e++) {
newArray.push(e);
}
else
newArray.push(i);
}
return newArray;
}
The most important reason why it isn't working is that you are treating your indices (i and e) as if they were the actual array elements (hence, the sub Arrays themselves). i is not the actual array, and does not have any array properties. It is just a number.
Each element must be referenced via the array[index], so in the case of the array argument, in the top loop, you would check array[i], but most importantly, if it is not an array, that is what you would push().
In your inner loop, you face a similar issue with e. However, you cannot simply do array[e] as the array you would be looking at would be array[i]. The proper way to address this is to make another variable for the array OR simply array[i][e]. Again, this is the value you would push().
I understand that this answer is a little vague, but it is intentionally so, as this is obviously an assignment from which you are trying to learn.
You need to use the value of the original array to push/concat into the new one. Also, you don't need to check the type, you can just concat everything:
var flatten = function (array) {
var newArray = [];
var arrayLength = array.length;
for (i = 0; i < arrayLength; i++) {
newArray = newArray.concat(array[i]);
}
return newArray;
}
if (array[i] instanceof Array)
Your algorithm looks fine, but you are referencing a Number index where you mean to be referencing an array element. Fix this in 3 places and your code should work.
Spoiler:
var flatten = function (array){
var newArray = [];
for (i = 0; i < array.length; i++) {
if (array[i] instanceof Array)
newArray = newArray.concat(array[i]);
else
newArray.push(array[i]);
}
return newArray;
}

Categories