Related
I have some problems with understanding how callback function should work. I wanted to do a function that works just like map method. Even though I don't recive any errors, elements in array don't change. Could you point what am I doing wrong?
function multiplyFn(x) {
return x * 2;
}
const exampleArray = [1, 2, 3, 4, 5, 6, 8];
function mapFn(array, callback) {
for (const el of array) {
callback(el);
console.log(el)
}
console.log(array)
return array;
}
mapFn(exampleArray, multiplyFn);
if you want to change the original array you can update the index of the array arguments that you pass in function.
function mapFn(array, callback) {
array.forEach(function(element,index){
let val= callback(element)
array[index] = val
});
return array;
}
You need to update the elements by the returned values:
function multiplyFn(x) {
return x * 2;
}
let exampleArray = [1, 2, 3, 4, 5, 6, 8];
function mapFn(array, callback) {
for (let i = 0; i < array.length; i++) {
let el = array[i];
array[i] = callback(el);
}
return array;
}
mapFn(exampleArray, multiplyFn);
Note you can do this simply using Array#map() which will not update original but return a new array
function multiplyFn(x) {
return x * 2;
}
const exampleArray = [1, 2, 3, 4, 5, 6, 8];
function mapFn(array, callback) {
return array.map(callback);
}
console.log(mapFn(exampleArray, multiplyFn));
If you want to implement your own map function, you can do it without using any of the in-built array methods
//Define your map method in the Array prototype object
Array.prototype.mymap = function(callback) {
const res = [];
for (let index = 0; index < this.length; index++) {
res[index] = callback(this[index], index, this);
}
return res;
}
const exampleArray = [1, 2, 3, 4, 5, 6, 8];
//Let's test with two examples
function multiplyFn(x) {
return x * 2;
}
const first = exampleArray.mymap(multiplyFn)
console.log(first)
const second = exampleArray.mymap((el, index, array) => ({el, index}))
console.log(second)
How can I make a function that returns only the numbers greater than the number that I entered?
My code here isn't working, and I don't know why.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var num = Number(prompt('number'));
function findBiggestNumbers(num) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] > num) {
num = arr[i];
}
}
return num;
// }
console.log(findBiggestNumbers(num));
To work with arrays you could use the filter function, it returns a subset of the array with some condition. So, you can simpley do:
var num = 5; //using 5 as an example
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var b = a.filter(number => number > num);
You can put this into an function.
You need to create a new empty array and fill it with numbers that are bigger than input value.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var num = Number(prompt('number'));
function FindBiggestNumbers(num) {
let biggerThanArray = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > num) {
biggerThanArray.push(arr[i]);
}
}
return biggerThanArray;
}
console.log(FindBiggestNumbers(num));
You can start to understand and do some fun things with functional JS.
Similar to the answer from Daladier Sampaio I've used filter to return an array where each element passes a condition (el > num) in the callback function. (filter, reduce, and map were introduced in ES5 and are very useful array methods and well worth learning how to use.)
In this example, I've passed in - and called - a whole function named greaterThan instead.
greaterThan
1) Accepts an argument - n, the number from the prompt in this case
2) Returns an array - the callback function that will operate on each array element. What's interesting about this function is that it carries a copy of num with it when it returns. A function like this that retains a copy of its outer lexical environment like that is called a closure. Understanding what they are and how they work is a useful JS skill, and one that is often picked up on in JS interviews.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const num = Number(prompt('number'));
// accepts a number and returns a callback function
// that accepts an array element and
// tests it against the value of `n`
function greaterThan(n) {
return function (el) {
return el > n;
};
}
// calling greater than with our prompted number
// returns that new callback function that checks each
// array element
const out = arr.filter(greaterThan(num));
console.log(out);
Modern JS >= ES6 will allow you to condense the amount of code you have to write using arrow functions. The following one-line code will work in place of the function in the example:
const greaterThan = n => el => el > n;
You could use Array.prototype.filter():
function FindBiggestNumbers(num) {
return arr.filter(n => n > num);
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var number = Number(prompt("Enter a number"));
console.log(FindBiggestNumbers(number));
The alternative is using a nested if statement inside a for loop like so:
First make a new array:
function FindBiggestNumbers(num) {
var newArr = [];
}
Then loop through the original array:
function FindBiggestNumbers(num) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
}
}
And if you find an element of the array greater than the number, add it to the new array:
function FindBiggestNumbers(num) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > num) {
newArr.push(arr[i]);
}
}
}
Finally, return the new array:
function FindBiggestNumbers(num) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > num) {
newArr.push(arr[i]);
}
}
return newArr;
}
Demonstration:
function FindBiggestNumbers(num) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > num) {
newArr.push(arr[i]);
}
}
return newArr;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var number = Number(prompt("Enter a number"));
console.log(FindBiggestNumbers(number));
Here is the question:
Compare two arrays and return a new array with any items only found in one of the two given arrays, but not both. In other words, return the symmetric difference of the two arrays.
And here is my code:
function diffArray(arr1, arr2) {
var newArr = [];
// Same, same; but different.
for (i = 0; i < arr1.length; i++) {
for (j = 0; j < arr2.length; j++)
while (arr1[i] === arr2[j])
delete arr2[j];
newArr = arr2;
}
return newArr;
}
console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));
Please, tell me my mistakes.
If you work using indices as references which you delete, you'll leave those indices undefined.
You have to use push to add an item and splice to remove one.
The time complexity of the following code should be: O(nm) where n and m are the lengths of the arr1 and arr2 arrays respectively.
function diffArray(arr1, arr2) {
var newArr = [];
for (i = 0; i < arr1.length; i++) {
for (j = 0; j < arr2.length; j++)
while (arr1[i] === arr2[j])
arr2.splice(j, 1);
newArr = arr2;
}
return newArr;
}
console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));
This should work, but I've found a different way that is a bit slower for short arrays but much faster for longer array.
The time complexity of the following code should be: O(3(n + m)), which is reduced to O(n + m) where n and m are the lengths of the arr1 and arr2 arrays respectively.
Look at this fiddle.
Here's it:
function diffArray(arr1, arr2) {
let obj1 = {}, obj2 = {};
for (let l = arr1.length, i = 0; i < l; i++)
obj1[arr1[i]] = undefined;
for (let l = arr2.length, i = 0; i < l; i++)
obj2[arr2[i]] = undefined;
let a = [];
for (let arr = arr1.concat(arr2), l = arr.length, i = 0, item = arr[0]; i < l; i++, item = arr[i])
if (item in obj1 !== item in obj2)
a.push(item);
return a;
}
console.log(diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]));
The task you are trying to complete asks you to create a new array, but instead you modify arr2. It would probably be easiest to just copy all elements not included in the other array to a new array, like this:
function diffArray(arr1, arr2) {
var newArray = [];
arr1.forEach(function(el) {
if (!arr2.includes(el)) {
newArray.push(el);
}
});
arr2.forEach(function(el) {
if (!arr1.includes(el)) {
newArray.push(el);
}
});
return newArray;
}
If you would rather try and fix your code instead, I can try to have another look at it.
I've used Array.prototype.filter method:
function diffArray(arr1, arr2) {
var dif01 = arr1.filter(function (t) {
return arr2.indexOf(t) === -1;
});
var dif02 = arr2.filter(function (t) {
return arr1.indexOf(t) === -1;
});
return (dif01).concat(dif02);
}
alert(diffArray([1, 2, 3, 6, 5], [1, 2, 3, 4, 7, 5]));
If you still want to use your code and delete the common elements, try to use Array.prototype.splice method instead of delete: the latter deletes the value, but keeps the index empty, while Array.prototype.splice will remove those whole indices within the given range and will reindex the items next to the range.
You can use Array.prototype.filter:
var array1 = [1, 2, 3, 5];
var array2 = [1, 2, 3, 4, 5];
var filteredArray = filter(array1, array2).concat(filter(array2, array1));
function filter(arr1, arr2) {
return arr1.filter(function(el) { return arr2.indexOf(el) < 0; });
}
Here is a working JSFiddle.
Try this:
function diffArray(arr1, arr2) {
var ret = [];
function checkElem(arrFrom, arrIn) {
for (var i = 0; i < arrFrom.length; ++i) {
var elem = arrFrom[i];
if (arrIn.indexOf(elem) === -1)
ret.push(elem);
}
}
checkElem(arr1, arr2);
checkElem(arr2, arr1);
return ret;
}
I hope this can solve your problem.
I am trying to solve this challenge Seek and Destroy. I can't figure out what is wrong. Any help ?
Seek and Destroy
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
This is the initial code below:
function destroyer(arr) {
// Remove all the values
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
This is my Code below:
function destroyer(arr) {
var letsDestroyThis = [];
var i =1 ; while (i<arguments.length) {
letsDestroyThis.push(arguments[i]);
i++;
}
for(var j=0 ; j< arguments[0].length; j++) {
for (var k= 0; k< letsDestroyThis.length; k++) {
if(arguments[0][j] === letsDestroyThis[k]){
arguments[0].splice(j, 1);
}
}
}
return arguments[0];
}
destroyer([2, 3, 2, 3], 2, 3);
Thanks in Advance!
You can create an array of all values that are supposed to be removed. Then use Array.filter to filter out these values.
Note: Array.splice will change original array.
function destroyer() {
var arr = arguments[0];
var params = [];
// Create array of all elements to be removed
for (var k = 1; k < arguments.length; k++)
params.push(arguments[k]);
// return all not matching values
return arr.filter(function(item) {
return params.indexOf(item) < 0;
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
function destroyer(arr) {
/* Put all arguments in an array using spread operator and remove elements
starting from 1 using slice intead of splice so as not to mutate the initial array */
const args = [...arguments].slice(1);
/* Check whether arguments include elements from an array and return all that
do not include(false) */
return arr.filter(el => !args.includes(el));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
This worked for me:
function destroyer(arr) {
// Remove all the values
var args = Array.from(arguments);
var filter = [];
for (i = 0; i < args[0].length; i++) {
for (j = 1; j < args.length; j++) {
if (args[0][i] === args[j]) {
delete args[0][i];
}
}
}
return args[0].filter(function(x) {
return Boolean(x);
});
}
console.log(
destroyer([1, 2, 3, 1, 2, 3], 2, 3)
);
//two ways of resolving the Seek and Destroy challenge on the FreeCodeCamp
//I was trying to simplify this code, please post your solutions, simplifying the code
//as much has its possible
function destroyer1 (arr){
//get array from arguments
var args = Array.prototype.slice.call(arguments);
args.splice(0,1);
for (var i = 0; i < arr.length; i++){
for(var j = 0; j < args.length; j++){
if(arr[i]===args[j]){
delete arr[i];
}
}
}
return arr.filter(function(value){
return Boolean(value);
});
}
//--------------------------------------
function destroyer(arr) {
// Remove all the values
//Get values from arguments of the function to an array, index 0(arr[0] will be "arr",
//rest of indexes will be rest of arguments.
var args = Array.from(arguments);
for (var i = 0 ; i < args[0].length; i++){
for (var j = 1; j < args.length; j++){
if(args[0][i] === args[j]){
delete args[0][i];
}
}
}
return args[0].filter(function(value){
return Boolean(value);
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
console.log(destroyer1([1,6,3,9,8,1,1], 3,1));
This is my Code:
function destroyer(arr) {
var argsBeRemove = [...arguments];
argsBeRemove.shift();
return arr.filter(val => {
return argsBeRemove.indexOf(val) == -1;
});
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Here is my version of Seek and Destroy. I assume that there are no zero elements in input (that assumption allows to pass the challenge). But that way I can make found elements equal zero and then just filter them out. It is pretty straight forward and no index mess when deleting elements in for loops.
function destroyer(arr) {
// Remove all the values
var args = Array.prototype.slice.call(arguments);
var temp = [];
temp = arguments[0].slice();
for (j = 1; j < args.length; j++) {
for (i = 0; i < arguments[0].length; i++) {
if (arguments[0][i] == arguments[j]) {
temp[i] = 0;
}
}
}
function isZero(value) {
return value !== 0;
}
var filtered = temp.filter(isZero);
return filtered;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
function destroyer(arr) {
var args = Array.prototype.slice.call(arguments, 1);
return arr.filter(destroyNum);
function destroyNum(element) {
return !args.includes(element);
}
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Give this a shot, it is way less convoluted:
function destroyer(arr) {
// arr1 is equal to the array inside arr
var arr1 = arr.slice(arguments);
// arr2 becomes an array with the arguments 2 & 3
var arr2 = Array.prototype.slice.call(arguments, 1);
// this function compares the two and returns an array with elements not equal to the arguments
return arr1.concat(arr2).filter(function(item) {
return !arr1.includes(item) || !arr2.includes(item)
})
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
The accepted solution returns a new array, instead of removing the elements from the existing array.
This can be achieved efficiently by iterating the array in reverse and removing any elements matching any of the filter arguments.
function destroy(original, ...matches) {
if('length' in original) {
let index = original.length
while(--index > -1) {
if(matches.includes(original[index])) {
original.splice(index, 1)
}
}
}
return original;
}
const original = [1, 2, 3, 1, 2, 3]
destroy(original, 2, 3)
console.log(original);
My answer is similar to previous one, but I didn't use indexOf. Instead of that I checked the values in cycle, but compiler gives me a warning to not to declare function in cycle.
function destroyer(arr) {
// Remove all the values
var temp = [];
for (var i = 1; i < arguments.length; i++) {
temp.push(arguments[i]);
arr = arguments[0].filter(function(value) {
return ( value !== temp[i - 1]) ;
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
We can get the arguments behind the array, which are the number required to be removed and store them to a list. Then, we can just use a filter to filter out the numbers that needed to be removed.
function destroyer(arr) {
let removeList=[...arguments].slice(1);
return arr.filter(e=>removeList.indexOf(e)===-1);
}
I know isn't the shortest way to do it, but i think is the more simple to understand in an intermediate level.
function destroyer(arr, ...elements) {
var i =0;
while(i<=arr.length){ //for each element into array
for(let j =0; j<elements.length; j++){ //foreach "elements"
if(arr[i]==elements[j]){ // Compare element arr==element
arr.splice(i,1); //If are equal delete from arr
i--; //Check again the same position
j=0;
break; //Stop for loop
}
}
i++;
}
return arr;
}
console.log(destroyer(["possum", "trollo", 12, "safari", "hotdog", 92, 65, "grandma", "bugati", "trojan", "yacht"], "yacht", "possum", "trollo", "safari", "hotdog", "grandma", "bugati", "trojan"));
console.log(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3));
function destroyer(arr) {
let newArray = Array.from(arguments).splice(1)
return arr.filter(item => !(newArray.includes(item)))
}
I'm trying to get a hang of JavaScript (again) and so far it's not going great.
The challenge:
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments. Remove all elements from the initial array that are of the same value as these arguments.
Why doesn't the code below remove the required elements for the second test case?
function destroyer(arr) {
console.log(arguments);
for (var array_i = 0; array_i < arr.length; array_i++){
for (var arg_i = 1; arg_i < arguments.length; arg_i++){
console.log("indexes", array_i, arg_i);
if (arr[array_i] === arguments[arg_i]){
console.log(arr[array_i], arguments[arg_i], "destroyed");
arr.splice(array_i, 1);
console.log(arr, arguments);
array_i = 0;
arg_i = 1;
}
}
}
return arr;
}
It successfully works here:
destroyer([3, 5, 1, 2, 2], 2, 3, 5);
But not here:
destroyer([2, 3, 2, 3], 2, 3);
You're trying to compensate for the elements deleted along the way by resetting your indices. It's much simpler (and actually works) if you delete from the end of the array. No resets needed.
function destroyer(arr) {
for (var array_i = arr.length - 1; array_i >= 0; array_i--){
for (var arg_i = 1; arg_i < arguments.length; arg_i++){
if (arr[array_i] === arguments[arg_i]){
arr.splice(array_i, 1);
break;
}
}
}
return arr;
}
console.log( destroyer([2, 3, 4, 2, 3], 2, 3) ); // [4]
console.log( destroyer([2, 3, 2, 3], 2, 3) ); // []
The problem is that you modify the array while you're looping.
You can use filter function to do the same:
function destroyer(arr) {
var args = [].slice.call(arguments);
return arr.filter(function(item) {
return args.indexOf(item) == -1;
});
}
document.getElementById('output').innerHTML =
JSON.stringify(destroyer([2,3,2,3], 2, 3)) + "\n" +
JSON.stringify(destroyer([1,2,3,4,2,3], 2, 3))
<pre id="output"></pre>
An alternative to reverse iteration using ES5 methods, and modifying the original array.
function destroyer(arr) {
var rest = Array.prototype.slice.call(arguments, 1);
rest.forEach(function(unwanted) {
var index = arr.indexOf(unwanted);
while (index > -1) {
arr.splice(index, 1);
index = arr.indexOf(unwanted);
}
});
return arr;
}
var initial1 = [2, 3, 2, 3];
destroyer(initial1, 2, 3);
document.getElementById('out1').textContent = JSON.stringify(initial1);
console.log(initial1);
var initial2 = [3, 5, 1, 2, 2];
destroyer(initial2, 2, 3, 5);
document.getElementById('out2').textContent = JSON.stringify(initial2);
console.log(initial2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.4.1/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js"></script>
<pre id="out1"></pre>
<pre id="out2"></pre>
The problem here is you are relying on length to loop through the element of array and simultaneously you are rearranging the elements of the array.
So what happens is after removing the 2 and 3, 2 again comes at 0th place and your counter is ahead now and will never cover the position 0th. So there will be other case too in which you will not get the desired result.
So instead of this try looping through each argument only once,
Select an argument and then search for it in the array.
for(var i = 1; i < arguments.length; i++)
{
var index = arr.indexOf(arguments[i]);
while(index > -1)
{
arr.splice(index, 1);
index = arr.indexOf(arguments[i]);
}
}
And you will get what you want.