Library Function to have Unique Items (remove duplicated) Array is not running - javascript

I am trying to make a "Library Function" to remove duplicated array entries. I have written following snippet but it doesn't seem to work. Can anyone help fix it?
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
Array.prototype.unique = function(arr){
var result = [];
arr.forEach(item){
if(result.indexOf(item) === -1){
result.push(item);
}
}
return result;
}
console.log(arr1.unique());

I believe what you are attempting to do is the following. The small change I made was to use the this keyword to reference the array itself. Also the function needs to be inside the foreach(fn => {}).
Array.prototype.unique = function() {
var result = [];
this.forEach(function(item) {
if(result.indexOf(item) === -1) {
result.push(item);
}
})
return result;
}
Making a version that uses an arrow function inside the foreach loop and uses includes, so you have some options.
Array.prototype.unique = function() {
var result = [];
this.forEach(item => {
if (!result.includes(item)) {
result.push(item);
}
})
return result;
}

Maybe this will help you.
No need to pass an argument, you can access array using this
var arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
Array.prototype.unique = function() {
var result = [];
this.forEach((item) => {
if (result.indexOf(item) === -1) {
result.push(item);
}
});
return result;
}
console.log(arr1.unique());

In console.log() must be :
console.log(arr1.unique(arr1));
your unique function receives an array as a parameter

Easy way to do this, You can try this
let arr1 = [5, 4, 2, 6, 9, 2, 8, 1, 6];
let result= Array.from(new Set(arr1))
console.log(result)

Related

How can I ignore non-present values in a function without returning undefined?

I have this code:
const removeFromArray = function(...xNumber) {
return xNumber.reduce(function(xArray, yNumber) {
for (let i = 0; i < xArray.length; i++) {
if (xArray[i] === yNumber) {
const index = xArray.indexOf(yNumber);
xArray.splice(index, 1);
} else if (xArray[i] !== yNumber) {
continue;
}
return xArray;
}
});
};
console.log(removeFromArray([3, 4, 5, 1], 1, 3, 5, 10));
It's supposed to take in arguments that, if they match with the elements in the array, they get deleted and it returns the new array. If the argument is not related to the elements in the array, it ignores it. This function works well if I write only numbers that are related to the elements in the array. If I write a number, such as 10, that's not inside the array, it returns undefined.
In order to solve this, I need to play with conditionals I assume?
I'm sure my mistake is in the else if conditional, having continue in there is not good, I just didn't know what else to do.
You can do a much simpler implementation using .filter()
const removeFromArray = function(array, ...numbersToRemove) {
return array.filter(item => !numbersToRemove.includes(item))
};
console.log(removeFromArray([3, 4, 5, 1], 1, 3, 5, 10));
Without arrow functions after the request in the comments
const removeFromArray = function(array, ...numbersToRemove) {
return array.filter(function(item) {
return !numbersToRemove.includes(item);
});
}
console.log(removeFromArray([3, 4, 5, 1], 1, 3, 5, 10));

Pass an array and further arguments into a function. How?

I have a function which takes an array and further arguments like this:
function arrayandmore([1, 2, 3], 2, 3)
I need to return the array ([1, 2, 3]) without those elements which equals the arguments coming behind the array. So in this case, the returned array would be:
([1]).
One of my approaches is:
function destroyer(arr) {
var args = Array.from(arguments);
var i = 0;
while (i < args.length) {
var result = args[0].filter(word => word !== args[i]);
i++;
}
console.log(result);
}
destroyer([1, 1, 3, 4], 1, 3);
Console returns:
[ 1, 1, 4 ]
I don't understand, why it returns one too - I don't understand, why it does not work.
It is the same with using splice.
function destroyer(arr) {
var args = Array.from(arguments);
var quant = args.length - 1;
for (var i = 1; i <= quant; i++) {
if (arr.indexOf(args[i]) !== -1) {
arr = arr.splice(arr.indexOf(args[i]));
}
console.log(arr);
}
}
destroyer([1, 1, 3, 4], 1, 3);
I think, both ways should work. But I don't figure out why they don't.
Your while won't work because result is being overwritten in every loop. So, it only ever removes the last parameter to the destroyer function
You can use the rest parameter syntax to separate the array and the items to be removed.
Then use filter and includes like this:
function destroyer(arr, ...toRemove) {
return arr.filter(a => !toRemove.includes(a))
}
console.log(destroyer([1, 1, 3, 4, 5], 1, 3))

Javascript have a function return no value

I've been trying to make a function that will not return any value if two values are the same between two arrays. I've searched my question several ways on here and on google, and everything I find says that a function HAS to return a value, and there's no way to avoid doing it. So I'm directly asking if there is a way, and if not how can I get around what I'm trying to do?
var bannedValues = [2, 4, 6, 8]; //Even numbers 1-8
var inputValues = [1, 2, 3, 4, 5, 6, 7, 8]; //All numbers 1-8
var filterValues = function(value)
{
for (var number of bannedValues)
{
if (value == number)
{
return; //I want this to return absolutely nothing, not even an empty value
}
}
return value;
}
var filteredValues = inputValues.map(filterValues);
console.log(filteredValues);
/* The array just gains "undefined" values in the places I want there
to be no value, so the array is a length of 8 instead of the 4 I want.
Can I somehow take those out or can I just not have them there in the first place? */
If you are using map, you are actually iterating through your array and manipulate it if necessary, but this will not remove item from array. Instead of map try filter
var bannedValues = [2, 4, 6, 8]; //Even numbers 1-8
var inputValues = [1, 2, 3, 4, 5, 6, 7, 8]; //All numbers 1-8
var filterValues = function(value) {
return bannedValues.indexOf(value)===-1;
}
var filteredValues = inputValues.filter(filterValues);
console.log(filteredValues);
result will be
(4) [1, 3, 5, 7]
Use the Array.filter() method:
var bannedValues = [2, 4, 6, 8]; //Even numbers 1-8
var inputValues = [1, 2, 3, 4, 5, 6, 7, 8]; //All numbers 1-8
filteredValues = inputValues.filter( function( el ) {
return bannedValues.indexOf( el ) < 0;
} );
/*This is another way to do it, but not supported in IE*/
filteredValues = inputValues.filter( function( el ) {
return !bannedValues.includes( el );
} );
console.log(filteredValues);
Lodash has an utility function for this as well: see here
JavaScript functions always have a return value. There's nothing you can do about that.
It's impossible I think to tell the difference between a function that explicitly returns undefined and one that just returns with no value expression.
If you want to do something like .map() but have the option of skipping values, use .reduce() instead:
var filterValues = function(accumulator, value)
{
for (var number of bannedValues)
{
if (value == number)
{
return accumulator;
}
}
accumulator.push(value);
return accumulator;
}
var filteredValues = inputValues.reduce(filterValues, []);

JavaScript - filter through an array with arguments using for loop

I am trying to use the filter method on an array to loop through the array based on a variable number of arguments.
Below is my attempt at this:
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
for (var i = 0; i < argArr.length; i++) {
return val != argArr[i];
};
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
When I do this, only the first element of the arguments array is disposed of. This therefore returns:
[1, 3, 1, 3]
I have found a few examples online of possible ways to resolve this but they are vastly different from what I understand just yet. Is there any way to get mine to work, or even understand why the additional elements of the arguments array are not being called.
If you use ES6 you can do it with rest operator and Array#includes function
function destroyer(arr, ...params){
return arr.filter(item => !params.includes(item));
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
With your logic you can do like this. If val is equal to the current argArr's item then return false, if nothing was found after the loop: return true
function destroyer(arr) {
var argArr = Array.prototype.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
for (var i = 0; i < argArr.length; i++) {
if(val === argArr[i]){
return false;
}
};
return true;
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Because with your code you always test if current element in filter is equal or not equal to second parameter in function which is 2 and return true/false. Instead you can use indexOf to test if current element in filter is inside arguments array.
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1);
var filteredArray = arr.filter(function(val) {
return argArr.indexOf(val) == -1
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Problem is in your this line
return val != argArr[i];
Change logic like this , it will avoid to do extra looping also .
function destroyer(arr) {
var argArr = arr.slice.call(arguments, 1); debugger
var filteredArray = arr.filter(function(val) {
return !(argArr.indexOf(val) >= 0);
});
console.log(filteredArray);
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);

Javascript fixing my flatten(array) function

I can not figure out why my code does not flatten out the nested arrays as indicated. I'd greatly appreciate some help here. I used a recursion to get to the actual value of the nested array. I tried to debug my code, and it seems to replace my results array every time the recursion takes place.
//Helper methods
function toType(obj){
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
function each(collection, callback){
if (Array.isArray(collection)){
for (var i = 0; i < collection.length; i++){
callback(collection[i], i, collection)
}
} else {
for (var i in collection){
callback(collection[i], i, collection)
}
}
}
//Flatten function
function flatten(array, isShallow=false, callback){
var results = [];
each(array, function(item){
if (!!isShallow && toType(item) === 'array'){
each (item, function(value){
results.push(value);
})
} else if (toType(item) !== 'array'){
results.push(item);
} else {
return flatten(item)
}
})
return results;
}
flatten([1, [2], [3, [[4]]]]);
// ---> [1]
Your problem appears to be with this line:
return flatten(item)
Returning here is a problem because the loop will end and the current entries in results will be ignored, as well as the remaining items. The line should be changed to instead append the results of
flatten(item)
to results array via push.
I recommend using a library for this sort of thing. http://underscorejs.org/#flatten is a great one!
Please see the refactored code below.
The major change is that instead of creating new copies of results, we are passing it to subsequent calls to flatten as a reference.
Please see the added comments
//Helper methods
function toType(obj){
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
function each(collection, callback){
if (Array.isArray(collection)){
for (var i = 0; i < collection.length; i++){
callback(collection[i], i, collection)
}
} else if(typeof collection === 'object'){
//type number was failing here
for (var i in collection){
callback(collection[i], i, collection)
}
}
else {
//default for primitive types
callback(collection, 0, collection);
}
}
//Flatten function
//Removed isShallow, how do we know if its shallow or not?
//Added results as arg, so we only manipulate the reference to results
//And to not create multiple scopes of var results;
function flatten(array, results, callback){
results = results || [];
each(array, function(item){
//removed 3rd if clause not needed.
//Only need to know if item is an object or array
if (toType(item) === 'array' || toType(item) === 'object'){
each (item, function(value){
flatten(value,results);
})
} else {
results.push(item);
}
})
return results;
}
var array1 = [1,[2,[3,4]]];
var array2 = [5,[6,[7,[8, {a:9,b:[10,11,12]}]]]];
var obj = {a:array1, b:array2};
console.log(flatten(array1)); // [ 1, 2, 3, 4 ]
console.log(flatten(array2)); // [ 5, 6, 7, 8, 9, 10, 11, 12 ]
console.log(flatten(obj)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]
You can do something like that:
function flatten(array, i) {
i = i || 0;
if(i >= array.length)
return array;
if(Array.isArray(array[i])) {
return flatten(array.slice(0,i)
.concat(array[i], array.slice(i+1)), i);
}
return flatten(array, i+1);
}
Example:
var weirdArray = [[],1,2,3,[4,5,6,[7,8,9,[10,11,[12,[[[[[13],[[[[14]]]]]]]]]]]]]
flatten(weirdArray);
//returns ==> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
The best way to flatten you array in javascript is to use splice function of Array. Please follow the following code. It works for nesting as well.
function flattenArray(arr){
for(var i=0;i<arr.length;i++){
if(arr[i] instanceof Array){
Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
}
}
return arr;
}
Use underscore.js's flatten function (http://underscorejs.org/#flatten). Underscore.js is a 3rd party library with 80 some-odd functions to make your life as a javascript programmer easier. Don't reinvent the wheel.
var _ = require('underscore');
_.flatten([1, [2], [3, [[4]]]]);
=> [1, 2, 3, 4];

Categories

Resources