Remove element from array if given in argument - javascript

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.

Related

Remove duplicates from sorted array and return length - Must mutate the original array

DISCLAIMER
I am well aware of the duplicate questions, however this one is asking to remove duplicates without making a new array and wants us to mutate the original array.
INSTRUCTIONS
Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
EXAMPLE
Given nums = [1,1,2],
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the returned length.
ATTEMPT
const removeDuplicates = function(nums) {
for(let i of nums){
if(nums[i] === nums[i]){
nums.splice(i, 1)
}
}
return nums.length;
};
console.log(removeDuplicates([1, 1, 2]));
console.log(removeDuplicates([1, 2]));
// [1, 1, 2] => [1, 2] (Correct)
// [1, 2] => [1] (Incorrect - should be [1, 2])
Am I mutating the array correctly with splice and what do I need to do to correct the 2nd argument?
Also, in leetcode, when I run the first argument, it says it's correct and returns the array of the leftover elements, but the instructions were asking for the length of the new array. Not sure if I'm missing something but why is it not returning the length?
https://imgur.com/5cuhFYf
Here you are:
const removeDuplicates = function(nums) {
for(let i = 0; i < nums.length;){
if(nums[i] === nums[++i]){
nums.splice(i, 1)
}
}
return nums.length;
};
console.log(removeDuplicates([1, 1, 2]));
console.log(removeDuplicates([1, 2]));
let nums = [1,1,2];
nums = [...new Set(nums)].length;
console.log(nums);
nums = [1,1,2];
nums = nums.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
console.log(nums)
For each element of the array you need to iterate through all remaining elements of that array, to check for all duplicates. Not sure if this is more performant then making a copy.
const removeDuplicates = function (nums) {
let i = 0;
while (i < nums.length) {
let j = i + 1;
while (j < nums.length) {
if (nums[i] === nums[j]) {
nums.splice(j, 1);
}
else {
j++;
}
}
i++;
}
return nums.length;
};
console.log(removeDuplicates([1, 1, 2]));
console.log(removeDuplicates([1, 2]));
console.log(removeDuplicates([1, 2, 1, 3, 4, 3, 2, 1]));
// [1, 1, 2] => [1, 2] (Correct)
// [1, 2] => [1] (Incorrect - should be [1, 2])
// [1, 2, 1, 3, 4, 3, 2, 1] => [1, 2, 3, 4]
The hint is in the line: It doesn't matter what you leave beyond the returned length.
Whoever is asking you this wants you to move through the array keeping track of 2 pointers: 1) The end of the output array and 2) the current index in the input array.
If you do this, and copy the input to the output pointer only when they're different, you will end up with the correct output, the correct length (from the output pointer) and a little bit of garbage at the end of the array.
const unique = (arr) => {
let output = 0;
for (let input = 0; input < arr.length; input++) {
if (arr[output] !== arr[input]) {
output++;
arr[output] = arr[input];
}
}
return output + 1;
}
const arr = [1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 8, 8, 8, 9, 11];
const length = unique(arr);
console.log(arr, length);
I believe this solution will pass more test cases (at least in my personal testing)
const removeDups = (nums) => {
// since mutating arrays I like to start at the end of the array so when the index is removed it doesn't impact the loop
let i = nums.length - 1;
while(i > 0){
// --i decrements then evaluates (i.e 5 === 4), i-- decriments after the evaluation (i.e 5 === 5 then decrements the last 5 to 4)
if(nums[i] === nums[--i]){
// remove the current index (i=current index, 1=number of indexes to remove including itself)
nums.splice(i,1);
}
}
console.log(nums);
return nums.length;
};
// Test Cases
console.log(removeDups([1,1,2])); // 2
console.log(removeDups([0,0,1,1,1,2,2,3,3,4])); // 5
console.log(removeDups([0,0,0,2,3,3,4,4,5,5])); // 5
Tried the solution provided by Kosh above, but it failed for bigger array [0,0,1, 1, 1, 2, 2, 3, 3, 4]. So ended up writing my own. Seems to work for all tests.
var removeDuplicates = function(nums) {
var i;
for (i = 0; i <= nums.length; i++) {
const tempNum = nums[i];
var j;
var tempIndex = [];
for (j = i+1; j <= nums.length; j++) {
if (tempNum === nums[j]) {
tempIndex.push(j)
}
}
nums.splice(tempIndex[0], tempIndex.length)
}
return (nums.length);
};

Filtering arguments from Arrays

The following code should take a given array and filter out all arguments that follow. For example the below code should return: [1, 1].
function destroyer(arr) {
var args= [];
args.push(arguments[0]);
var realArgs = args[0];
var filteredArr=[];
function removeIt (val){
return val != ;
}
filteredArr= realArgs.filter(removeIt);
return filteredArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
I can't figure out the filter function. Do I need to use Boolean somehow?
If you want to access the arguments of the function you should use arguments not args. The filtering part is not straightforward because javascript still doesn't have a builtin function we can use, so we have to implement it by ourselves (that's the includes function).
function destroyer(arr) {
var arr = arguments[0];
var toFilter = [];
for (var i = 0; i < arguments.length; i++)
toFilter.push(arguments[i]);
function removeIt (arr, numsToFilter){
var array = arr.slice(); // make sure to copy the array in order not to modify the original
for (var i = 0; i < array.length; i++) {
if (includes(numsToFilter, array[i])) {
delete array[i];
}
}
return array;
}
function includes(arr, k) {
for(var i=0; i < arr.length; i++){
if( arr[i] === k){
return true;
}
}
return false;
}
return removeIt(arr, toFilter);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Running the code-example
You can call Array#slice on the arguments object to convert it to an array. We'll slice from the index 1 (skip the arr). Then you can Array#filter the arr array. On each iteration check if the item is in the toRemove array by using Array#indexOf. Items that are in toRemove will be filtered out. Note - Array#filter returns a new array.
function destroyer(arr) {
// convert all the arguments but arr into array
var toRemove = [].slice.call(arguments, 1);
// filter the original array
return arr.filter(function removeIt(val){
// keep all vals that are not in the toRemove array
return toRemove.indexOf(val) === -1;
});
}
var result = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
console.log(result);

Javascript: How to find first duplicate value and return its index?

I have to find first duplicate value in array and then return its index in variable firstIndex. This has to be done with for loop which should stop after having found first duplicate. I know this is probably pretty simple but I got stuck. So far I have this but it doesn't seem to be working:
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b])
firstIndex = numbers4.indexOf(numbers4[a]);
break;
}
}
console.log(firstIndex);
Console prints out 1 which is fine because 2 is first duplicate, but when I change numbers in array, the loop doesn't work. Can you advise what can be changed here?
Thanks in advance!
If I correctly understand your question, that's should help you...
Basically, you need for a double iteration.
const firstDupeIndex = list => list.findIndex(
(item, index) => list.lastIndexOf(item) !== index
);
console.log(
"First Dupe at index:",
firstDupeIndex([5, 2, 3, 4, 4, 6, 7, 1, 2, 3])
);
Thee above implementation comes with the drawback of being O(n2), due to nesting the lastIndexOf within the findIndex function.
A better solution would be to index your occurrences by building a dictionary, therefore keeping time complexity to just O(n) in the worst case. Probably a little bit less neat, but surely more efficient with big inputs.
const firstDupeIndex = (list) => {
const dict = {};
for (const [index, value] of list.entries()) {
if (dict.hasOwnProperty(value)) {
return dict[value];
}
dict[value] = index;
}
return -1;
};
console.log(
"First Dupe at index:",
firstDupeIndex(['a', 'b', 'c', 'd', 'e', 'b', 'z', 't', 'c'])
);
Change your code with the following
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
var isMatch=false;
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]){
firstIndex = numbers4.indexOf(numbers4[a]);
isMatch=true;
break;
}
}
if (isMatch) {break;}
}
console.log(firstIndex);
I would use an object remembering the values already found... Something like that should work ;)
var numbers4 = [5, 2, 3, 4, 4, 6, 7, 1, 2, 3];
function findFirstDuplicateIndex(arr){
var found = {};
for (var a = 0, aa = arr.length; a < aa ; a++) {
if (found[arr[a]])
return found[arr[a]];
found[numbers4[a]] = a
}
}
console.log(findFirstDuplicateIndex(numbers4));
It's quite fast because you just loop one time through the array. The rest of the time you just access an object property or you set the object property... Let me know if you have questions ;)
However maybe there something faster... It's just an idea ^^
PS: It also works with words, not just numbers
Your break; terminates b loop, because if() is not using parenthesis {}.
Additionally, firstIndex should be simply set to either a or b depending on whether you need to return the duplicate's first occurance or first repetition.
It should be:
if (numbers4[a] === numbers4[b])
{
firstIndex = a;
break;
}
Your problem is - you have two loops and only one break, you need to break out of both.
Why not simply return the index as soon as values match?
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
function getDuplicate(numbers4)
{
for (var a = 0; a < numbers4.length; a++) {
for (var b = a+1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]){
return a;
}
}
}
}
console.log(getDuplicate(numbers4 ));
However, you can optimize your code further by keeping a map
function getDuplicate( numbers )
{
var map = {};
for (var a = 0; a < numbers.length; a++)
{
if( map[ numbers[ a ] ] )
{
return a;
}
map[ numbers[ a ] ] = true;
}
return -1;
}
You can check if indexOf() is not equal to lastIndexOf() and return value and break loop
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var i = 0; i < numbers4.length; i++) {
if (numbers4.indexOf(numbers4[i]) != numbers4.lastIndexOf(numbers4[i])) {
firstIndex = i;
break;
}
}
console.log(firstIndex)
You don't even need nested for loops.
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 1; a < numbers4.length; a++) { //start from second elem since first is never a duplicate
if (numbers4.lastIndexOf(numbers4[a])> a) {
firstIndex = a;
break;
}
}
console.log(firstIndex); //1
All you have to do during iterating is to check if current value exists somewhere further in array. That is done by checking last index of this value's occurrence using lastIndexOf().
var numbers = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex;
var len = numbers.length;
for (var i = 0; i < len; i++) {
var tmpArray = numbers.slice(i + 1, len);
var index = tmpArray.indexOf(numbers[i]);
if (index !== -1) {
firstIndex = index + i + 1;
break;
}
}
console.log(firstIndex);
Update:
Actually your logic is right, but you missed braces for if condition and also if the condition satisfies then it means firstIndex is the same as a
This is your code with braces,
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3];
var firstIndex = "";
for (var a = 0; a < numbers4.length; a++) {
for (var b = a + 1; b < numbers4.length; b++) {
if (numbers4[a] === numbers4[b]) {
firstIndex = a
break;
}
}
}
console.log(firstIndex);
The question states the first dupe in the array has to be found along with it's index. So I return an object where the i property is the index and the e property is the first duplicate element itself. One way of performing this task would be
var numbers4 = [5, 2, 3, 4, 2, 6, 7, 1, 2, 3],
headDupe = (a,r={}) => (r.e = a.find((n,i) => (r.i = a.indexOf(n), r.i < i)),r);
console.log(headDupe(numbers4));

The sum of a range using Javascript

I wish to execute a program with output as :
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1, 10)));
// → 55
I am getting an error for array.length.Please find the code below:
var array = [];
function range (arr){
var lower = Math.min(arr[0],arr[1]);
var upper = Math.max(arr[0],arr[1]);
for (var i=lower;i<=upper;i++){
array.push(i);
}
}
function sum(array){
for(var i=0;i < array.length;i++){
var total = total+array[i];
}
}
console.log(sum(range(1, 10)));
I am at begineers level, please do help.
Thanks.
You have a few problems here:
1.) You aren't returning anything in your range function. You need to return the filled array.
2.) You aren't passing the array correctly in the sum function call.
3.) You aren't returning anything in your sum function call.
Without returning any values, you aren't letting your code blocks work with eachother
var array = [];
function range (arr){
var lower = Math.min(arr[0],arr[1]);
var upper = Math.max(arr[0],arr[1]);
for (var i=lower;i<=upper;i++){
array.push(i);
}
return array; // return the array to be used in the sum function
}
function sum(array){
var total = 0; // need to create a variable outside the loop scope
for(var i in array){
total = total+array[i];
}
return total;
}
console.log(sum(range([1,10]))); // pass the array correctly
Note that you need to set the total variable outside the scope of the for-loop within the sum function. That way you can return the final value. Otherwise, it would return undefined.
See the fiddle: https://jsfiddle.net/udyhb95a/
You need to pass an array when calling the range function you defined range([1, 10])
You need to rewrite your sum function
As a side note, there are more efficient ways to compute the sum of a range of elements without iterating on them.
function sum_of_range(start, end) {
return end * (end + 1) / 2 - start * (start + 1) / 2;
}
Edit:
Here is a working sum function
function sum(array) {
var accumulator = 0;
for (var i = 0; i < array.length; ++i)
accumulator += array[i];
return accumulator;
}
Here you declare a function with one parameter as an array
function range (arr){
...
But here you call a function with two arguments as numbers
console.log(range(1, 10));
Use this call function
console.log(range([1, 10]));
And don't use for..in for arrays
for(var i in array){ it doesn't work as you expect
Use forEach function or plan for loop
Also you have some error in sum function
See working example below:
function range(arr) {
var array = [];
var lower = Math.min(arr[0], arr[1]);
var upper = Math.max(arr[0], arr[1]);
for (var i = lower; i <= upper; i++) {
array.push(i);
}
return array;
}
function sum(array) {
var total = 0;
for (var i = 0; i < array.length; i++) {
total = total + array[i];
}
return total;
}
document.write('range ' + range([1, 10]) + '<br>');
document.write('sum ' + sum(range([1, 10])));
You need to modify sum & range function
function range (){
var array = [];
var lower = Math.min.apply(null, arguments);
var upper = Math.max.apply(null, arguments);
for (var i=lower;i<=upper;i++){
array.push(i);
}
return array;
}
function sum(array){
return array.reduce((x,y)=>x+y,0);
}
console.log(range(1, 10));
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1)); //if we are considering min & max from params
// [-1, 0, 1, 2, 3, 4, 5]
console.log(sum(range(1, 10)));
// 55
Hello Dear check it now.
var array = [];
function range(arr, arr1) {
var lower = Math.min(arr);
var upper = Math.max(arr1);
for (var i = lower; i <= upper; i++) {
array.push(i);
}
}
function sum() {
var total = 0;
for (var i = 0; i < array.length; i++) {
total = total + array[i];
}
return total;
}
console.log(sum(range(1, 10)));
This is the correct answer to the problem at the end of the data structures chapter within Eloquent JavaScript
function range(start, end, step) {
let arr = []; //declare an empty array
var step = step || 1;//tests to see if step was supplied, otherwise it's 1
if(start < end)
{
for(let i = start; i <= end; i += step)
{
arr.push(i);
}
}
else
{
for(let i = start; i >= end; i += step)
{
arr.push(i);
}
}
return arr;
}
function sum(array) {
let total = 0;
for(let i = 0; i < array.length; i++)
{
total += array[i];
}
return total;
}
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(range(5, 2, -1));
// → [5, 4, 3, 2]
console.log(sum(range(1,10)));
// → 55
This solution takes into account of entering a step that isn't expected to be positive/negative, i.e range from 1 to 5, we would expect step to be positive, but if the user somehow entered a negative step then an empty array would occur.
The browser actually hangs for the opposite, if the array is expected to decrease, but the step sizes are > 0.
'use strict';
function range(start, end, step = 1){
let output = [];
if (start > end){
// Sanity check, all steps if expected to go down should be negative
if (step > 0){
step = -step;
}
for (;start >= end; start += step){
console.log(start);
output.push(start);
}
}
else{
// Likewise, as all steps should be positive
if (step < 0){
step = -step;
}
for (;start <= end; start += step){
output.push(start);
}
}
return output;
}
function sum(arr){
let output = 0;
for (let i of arr){
output += i;
}
return output;
}
console.log(range(1, 5, 1));
// → [1, 2, 3, 4, 5]
console.log(range(5, 1, -1));
// → [5, 4, 3, 2, 1]
// Notice this one step is a positive, but this is handled (original solution returned empty array)
console.log(range(5, 1, 1));
// → [5, 4, 3, 2, 1]
console.log(sum(range(1,10)));
// → 55
An improvement onto this is to use the reduce function for an array to sum instead of a for loop, i.e:
function sum(array){
return array.reduce((x,y)=>x+y,0);
}
For people finding this later on as I did, here is a way to write the range function so you can pass the input as written in the original question:
console.log(sum(range(1, 10)));
…and a cleaned up sum function similar to the one in A. Sharma's answer:
function range(lower, upper) {
let array = []
for (let i = lower; i <= upper; i++) {
array.push(i);
}
return array;
}
function sum(array) {
let total = 0;
for (let i in array) {
total = total + array[i];
}
return total;
}
console.log(sum(range(1, 10)));
Also worth mentioning:
The use of reduce in JagsSparrow's answer, which is elegant, while not entirely obvious and newcomer friendly as Mathias Vonende pointed out.
Negative step tolerant versions in answers from Jimmy Wei and user3225968.
This is the best solution I've got
function range(x,y){
var arr = [];
for(x;x<=y;x++){
arr.push(x);
};
return arr;
};
function sum(array){
return array.reduce((a,b) => a + b, 0);
};
console.log(sum(range(1,10)));
This answer is quite late but I am learning these things now and want to share my solution. I have not seen this solution provided for the specific question "Sum of a range in Javascript" so I wanted to share it. What I have done here is made use of the pop method for the array which allowed me not to specifically pass an array argument to the range function but to provide a solution to the argument in the way it was originally presented in the question.
var result = [];
var counter = 0;
function range(start, end) {
for (let i = start; i <= end; i++) {
result.push(i);
}
return result;
}
function sum(array) {
for (let i = 0; i < result.length; i++) {
counter += result.pop(i);
}
return counter;
}
console.log(range(1, 10));
// → [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(sum(range(1, 10)));
// → 55
This can be accomplished very easily and efficiently without any globally scoped vars.
It's not clear in the original question what behavior should be applied to the -1 argument. It seems to be an indicator to reverse the range. In the below example, I've used a boolean to check this argument. A value of -1 would actually be the same as not providing a third argument. To reverse the range, pass in any truthy value.
function range(from, to, reverse) {
// Make sure our inputs are actually numbers
if (Number(from) != from || Number(to) != to) {
throw new TypeError("range() expects a Number as both it's first and second argument");
}
let o = []; // initialize our output array
// get the lowest value argument as our starting index
let i = Math.min(from, to);
// get the highest value argument as our ending index
let x = Math.max(from, to);
// push i onto our output array and then increment until i == x
while (i <= x) { o.push(i); i++; }
// reverse the range order if necessary
if (reverse) { o = o.reverse(); }
// return our output array
return o;
}
Then we can use Array.reduce to iterate through the range array and add each value (b) to the one before it (a) with the addition assignment operator (+=).
function sum(range) {
if (!(range instanceof Array)) {
throw new TypeError("sum() expects an Array as it's only argument");
} return range.reduce((a,b) => a+=b);
}
Testing it:
let a = range(1,10);
let b = range(5,2);
let c = range(5,2,true);
let d = range(3,-1);
let e = range(10,10);
console.log(a); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(b); // [ 2, 3, 4, 5 ]
console.log(c); // [ 5, 4, 3, 2 ]
console.log(d); // [ -1, 0, 1, 2, 3 ]
console.log(e); // [ 10 ]
console.log(range('test', 10)); // TypeError
console.log(range(1, 'test')); // TypeError
console.log(sum(a)); // 55
console.log(sum(b)); // 14
console.log(sum(c)); // 14
console.log(sum(d)); // 5
console.log(sum(e)); // 10
console.log(sum('test')); // TypeError
here my answer, I'd glad if you give me feedback about this solution.
let arr = [];
function range(x, y) {
for (let i = x; i <= y; i++) {
arr.push(i);
}
return arr;
}
function sum(array) {
const many = array.reduce((total, number) => {
return total + number;
}, 0);
return many;
}
console.log(sum(range(1, 10)));

freecodecamp Challenges- Seek and Destroy

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)))
}

Categories

Resources