Arguments for the Seek and Destroy Freecode camp challenge - javascript

I'm trying to understand the Seek and Destroy challenge below.
Task: 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);
After several (really) several attempts and looking at other people's code, I was able to resolve the task. However, I think it was more out of luck. I’ve copied my code below, but I was hoping someone could clarify a couple of things for me.
The code below passes whether I return val or args within the iterateThroughArray function. Why is that?
If I am supposed to be comparing ALL arguments against the first argument, where in this code am I indicating that? I kept thinking I needed to splice the first argument to compare all other arguments against it or create a variable for argument[0]. Any guidance you can provide is greatly appreciated!
function destroyer(arr) {
var args = Array.from(arguments); //this also converts them to an array
var iterateThroughArr = function (val) {
if (args.indexOf(val) ===-1){
return args;
}
};
return arr.filter(iterateThroughArr);
}

This may sound a lot to take in but here is my explanation
function destroyer(arr) {
var args = Array.from(arguments); //Here arr is converted to [Array(6),2,3]
//console.log(args)
/* var iterateThroughArr = function (val) {
if (args.indexOf(val) ===-1){
return args;
}
};
return arr.filter(iterateThroughArr);
*/
// to make more clear the above code can be rewritten as below
var arr = arr.filter(function (val) {
console.log("args = "+ args + " val = " + val + " indexOf(val) " + args.indexOf(val) )
// here you are itterating through each arr val which in this case is[1,2,3,1,2,3]
// if you dont believe me uncomment the next console.log() and see the output
// console.log(val)
if (args.indexOf(val) ===-1){
// here is where the magic happens
// Now you are checking if val exisists by using a builtin method called .indexOf()
// In general, .indexOf() returns -1 if a value does not exist within an array
//Below is working example
/* var array = [1,2,3,4,5]
console.log(array.indexOf(1)) // 0 since it is located at index 0
console.log(array.indexOf(5)) // 4 since it is located at index 4
console.log(array.indexOf(10)) // -1 since it does not exisit
*/
// Therefore, if value passes the above if statement
//then that means it doesnot exisit on args([Array(6),2,3])
//which as a result will be included on the filtered array
return args;
}
});
return arr;
}
var val = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
//console.log(val)
Basically, what you need to understand is how filter works and how .indexOf works.
For more detail visit Mozilla documentation: .indexOf() and .filter()

Give this a try:
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);

Related

In javascript find () method of an array how to get any element using only array argument of the callback function? See the code below

var check = [1,2,3,4,5,6];
var check1 =check.find((elements,index,array)=>{ return array ;}); console.log(check1);
Output is 1. Why? And if i want 3 as output from above array by giving checks or condition to the array argument then how to get it?
The find method executes the callbackFn function once for each index of the array until the callbackFn returns a truthy value. If so, find immediately returns the value of that element. Otherwise, find returns undefined.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
And since you aren't really doing any checks and just returning c (a truthy value), which is the array itself, that's why it returns 1.
If you want to find 3 or any other value, you do the following (also name your function params better so it's easier to understand what is going on):
var check = [1, 2, 3, 4, 5, 6];
var check3 = check.find((element, index, array) => {
return element === 3
});
console.log(check3); // output : 3
In response to OP request in comments. The third parameter of the callback function passed into array.find can be used to modify the original array based on a condition. This example switches even values to the odd value 1.
const check = [1,2,3,4,5,6]
check.find((el, index, arr) => {
if (el % 2 === 0){
arr[index] = 1
}
})
console.log(check) // [2,2,3,4,5,6]
However, this is not the proper use of .find, and .find should not be used in this way. .find should be used to simply return the first value of an array that satisfies a condition, as decho explained in his answer. If you are wanting to update the values in an array consider using a for loop or .forEach.
Based on your comment here's how to check if a number exists at a particular index, and returning the number based on that check.
var check = [1, 2, 3, 4, 5, 6];
var check1 = check.find((el, i, arr) => {
return arr.indexOf(3) > 1 && el === 3;
});
var check2 = check.find((el, i, arr) => {
return arr.indexOf(3) > 3 && el === 3;
});
console.log(check1);
console.log(check2);

Iterating inside JavaScript filter method

I am trying to compare two given parameters of a function. The exact problem is as follows:
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.
Note
You have to use the arguments object.
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3)); // expected output: [1,1]
I am using filter method to iterate over the array but I couldn't compare the args with the elements of the array inside the callback of the filter.
function destroyer(arr, ...args) {
let result = arr.filter(num => {
for (let i = 0; i<=args.length; i++ ){
num !== args[i]
}
});
return result;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
I can iterate with for loop but I cannot use the output of for loop to do filter iteration.
Any ideas?
Probably an easier way to achieve the goal using .filter() with .includes(). Additionally you can use ...rest so called rest parameters for you function, see form the documentation:
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
Try as the following:
const destroyer = (arr, ...rest) => {
return arr.filter(num => !rest.includes(num));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
I hope this helps!
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Example:
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
via MDN
Filter iterates over all elements of some array and returns a new array. It puts an element in the new array only if callback (your function invoked as a parameter of filter) return true otherwise it's omitted.
Next it's worth to use rest parameters to achieve two arrays (initial and values to exclude).
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
function sum(...theArgs) {
return theArgs.reduce((previous, current) => {
return previous + current;
});
}
console.log(sum(1, 2, 3));
// expected output: 6
console.log(sum(1, 2, 3, 4));
// expected output: 10
Solution with explanation:
//Declare your function, first parameter is initial array, the second one is also array created by using rest parameters
function destroyer(initialArray = [], ...toExclude) {
// filter initialArray, if el (single element) is NOT included in "toExclude" it returns true
// and add this particular element to the result array
let result = initialArray.filter(el => toExclude.includes(el) == false);
//return result
return result;
}

Spinning the elements of an array clockwise in JS

I am supposed to rotate an array of integers clockwise in JS.
Here is my code for it:
function rotateArray(N, NArray)
{
//write your Logic here:
for(j=0;j<2;j++){
var temp=NArray[N-1];
for(i=0;i<N-1;i++){
NArray[i+1]=NArray[i];
}
NArray[0]=temp;
}
return NArray;
}
// INPUT [uncomment & modify if required]
var N = gets();
var NArray = new Array(N);
var temp = gets();
NArray = temp.split(' ').map(function(item) { return parseInt(item, 10);});
// OUTPUT [uncomment & modify if required]
console.log(rotateArray(N, NArray));
The code accepts an integer N which is the length of the array. The input is as follows:
4
1 2 3 4
The correct answer for this case is supposed to be
4 1 2 3
But my code returns
4 1 1 1
I cannot find where my code is going wrong. Please help me out.
All you need to do is move one item from the end of the array to the beginning. This is very simple to accomplish with .pop() (removes an item from the end of an array), then declare a new array with that element as the first:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem, ...NArray];
}
console.log(rotateArray(1, [1, 2, 3, 4]));
Doing anything else, like using nested loops, will make things more unnecessarily complicated (and buggy) than they need to be.
If you don't want to use spread syntax, you can use concat instead, to join the lastItem with the NArray:
function rotateArray(N, NArray) {
const lastItem = NArray.pop();
return [lastItem].concat(NArray);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
If you aren't allowed to use .pop, then look up the last element of the array by accessing the array's [length - 1] property, and take all elements before the last element with .slice (which creates a sub portion of the array from two indicies - here, from indicies 0 to the next-to-last element):
function rotateArray(N, NArray) {
const lastItem = NArray[NArray.length - 1];
const firstItems = NArray.slice(0, NArray.length - 1);
return [lastItem].concat(firstItems);
}
console.log(rotateArray(1, [1, 2, 3, 4]));
function rotate(array,n){
Math.abs(n)>array.length?n=n%array.length:n;
if(n<0){
n=Math.abs(n)
return array.slice(n,array.length).concat(array.slice(0,n));
}else{
return array.slice(n-1,array.length).concat(array.slice(0,n-1));
}
}
console.log(rotate([1, 2, 3, 4, 5],-3));
The answer by #CertainPerformance is great but there's a simpler way to achieve this. Just combine pop with unshift.
let a = [1,2,3,4];
a?.length && a.unshift(a.pop());
console.log(a);
You need to check the length first so you don't end up with [undefined] if you start with an empty array.

Sorting array multiple times and storing in an object [duplicate]

Let's suppose I wanted a sort function that returns a sorted copy of the inputted array. I naively tried this
function sort(arr) {
return arr.sort();
}
and I tested it with this, which shows that my sort method is mutating the array.
var a = [2,3,7,5,3,7,1,3,4];
sort(a);
alert(a); //alerts "1,2,3,3,3,4,5,7,7"
I also tried this approach
function sort(arr) {
return Array.prototype.sort(arr);
}
but it doesn't work at all.
Is there a straightforward way around this, preferably a way that doesn't require hand-rolling my own sorting algorithm or copying every element of the array into a new one?
You need to copy the array before you sort it. One way with es6:
const sorted = [...arr].sort();
The spread-syntax as array literal (copied from mdn):
var arr = [1, 2, 3];
var arr2 = [...arr]; // like arr.slice()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator
Just copy the array. There are many ways to do that:
function sort(arr) {
return arr.concat().sort();
}
// Or:
return Array.prototype.slice.call(arr).sort(); // For array-like objects
Try the following
function sortCopy(arr) {
return arr.slice(0).sort();
}
The slice(0) expression creates a copy of the array starting at element 0.
You can use slice with no arguments to copy an array:
var foo,
bar;
foo = [3,1,2];
bar = foo.slice().sort();
You can also do this
d = [20, 30, 10]
e = Array.from(d)
e.sort()
This way d will not get mutated.
function sorted(arr) {
temp = Array.from(arr)
return temp.sort()
}
//Use it like this
x = [20, 10, 100]
console.log(sorted(x))
Update - Array.prototype.toSorted() proposal
The Array.prototype.toSorted(compareFn) -> Array is a new method which was proposed to be added to the Array.prototype and is currently in stage 3 (Soon to be available).
This method will keep the target Array untouched and returns a copy of it with the change performed instead.
Anyone who wants to do a deep copy (e.g. if your array contains objects) can use:
let arrCopy = JSON.parse(JSON.stringify(arr))
Then you can sort arrCopy without changing arr.
arrCopy.sort((obj1, obj2) => obj1.id > obj2.id)
Please note: this can be slow for very large arrays.
Try this to sort the numbers. This does not mutate the original array.
function sort(arr) {
return arr.slice(0).sort((a,b) => a-b);
}
There's a new tc39 proposal, which adds a toSorted method to Array that returns a copy of the array and doesn't modify the original.
For example:
const sequence = [3, 2, 1];
sequence.toSorted(); // => [1, 2, 3]
sequence; // => [3, 2, 1]
As it's currently in stage 3, it will likely be implemented in browser engines soon, but in the meantime a polyfill is available here or in core-js.
I think that my answer is a bit too late but if someone come across this issue again the solution may be useful.
I can propose yet another approach with a native function which returns a sorted array.
This code still mutates the original object but instead of native behaviour this implementation returns a sorted array.
// Remember that it is not recommended to extend build-in prototypes
// or even worse override native functions.
// You can create a seperate function if you like
// You can specify any name instead of "sorted" (Python-like)
// Check for existence of the method in prototype
if (typeof Array.prototype.sorted == "undefined") {
// If it does not exist you provide your own method
Array.prototype.sorted = function () {
Array.prototype.sort.apply(this, arguments);
return this;
};
}
This way of solving the problem was ideal in my situation.
You can also extend the existing Array functionality. This allows chaining different array functions together.
Array.prototype.sorted = function (compareFn) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]
Same in typescript:
// extensions.ts
Array.prototype.sorted = function (compareFn?: ((a: any, b: any) => number) | undefined) {
const shallowCopy = this.slice();
shallowCopy.sort(compareFn);
return shallowCopy;
}
declare global {
interface Array<T> {
sorted(compareFn?: (a: T, b: T) => number): Array<T>;
}
}
export {}
// index.ts
import 'extensions.ts';
[1, 2, 3, 4, 5, 6]
.filter(x => x % 2 == 0)
.sorted((l, r) => r - l)
.map(x => x * 2)
// -> [12, 8, 4]

JavaScript - How to increase all the element in int array by 1

How to increase all the element in an int array by 1?
Ex:
make var a = [1,2,3,4] and increase all elements inside so that the result gives
a = [2,3,4,5]
Is there any method except doing a = a+[1,1,1,1]?
Nowadays it is being done with the arrow functions as following :)
console.log([1,2,3,4].map(v=> v+1));
Sure. Just use the JavaScript map function.
[1,2,3,4].map(function(entry) {
return entry+1;
});
As per MDN docs;
The map() method creates a new array with the results of calling a
provided function on every element in this array.
Another example of the map function in action provided by the MDN I added is;
var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles is now [2, 8, 18]
You can take advantage of the map() function, which will map each item within your array to a function that can be used to transform it:
[1,2,3,4].map(function(item) {
// Increment each item by 1
return item + 1;
});
Example
console.log([1, 2, 3, 4].map(function(item) {
return item + 1;
}));
You can use the map function
var a = [1,2,3,5];
var x = a.map(function(item){
return item+1;
})
console.log(x)
DEMO

Categories

Resources