javascript: remove values from an array that are in a second array - javascript

Using pure javascript, starting with an array, I would like to return and array by removing values that match any value in a second array.
I have solved this problem, but I believe with more code than is really necessary.
I am hoping for a more concise or elegant solution using only javascript.
function removeValues(arr){
array = arguments[0];
args = Array.prototype.slice.call(arguments);
len = arguments.length;
filtered = array.filter(function(n){
x = true;
for (var i = 1; i < len; i++) {
if (n == args[i]) { x = false; }
}
return x;
});
return filtered;
}
removeValues([1,2,3,1,2,3],2,3);
Should use a function that removes values from the first argument (an array) using values in one or more additional arguments.

When you're working with the filter function is not necessary to use loops because you're already in a loop. After converting the arguments into an array with [].slice.call(arguments), you could use indexOf that is responsible for returning the position of a value in an array, if a value is not exists, this returns -1, so we will take all the results that are -1
Your code could be reduced as well:
function removeValues(arr){
return arr.filter(function(val){
return [].slice.call(removeValues.arguments).slice(1).indexOf(val) === -1
})
}
console.log(removeValues([1,2,3,1,2,3],2,3))
ES6 Method: Using Rest parameters and Arrow Functions
var removeValues = (arr, ...values) => arr.filter(val => values.indexOf(val) === -1)

Try this instead...
function removeValues(){
var args = Array.prototype.slice.call(arguments).slice(1);
return arguments[0].filter(function(value) {
return args.indexOf(value) === -1;
});
}
removeValues([1, 2, 3, 1, 2, 3], 2, 3);
It does the exact same thing, but tidies it slightly.

Try like this:
var array1 = [ 1, 2, 3, 4, 5 ];
var array2 = [ 2, 3 ];
var result = array1.filter( function ( elem ) {
return array2.indexOf( elem ) === -1;
});
See example: Running code

Related

how to print a unique number in a array

The problem is to find the unique number in a array such as [2,2,2,5].
The output should be 5 as it is the 1 unique element in the array.
I have attempted this:
function findUniq(arr) {
var b= arr[0];
var c;
for(var i=0; i<arr.length; i++)
{
if(arr[i]===b )
{
b=arr[i]
}
else
{
c=arr[i];
}
}
return c
console.log(findUniq([3, 5, 3, 3, 3]))
This works fine unless the unique number is the first element in the array. How do I fix this?
You can use indexOf and lastIndexOf to see if a value occurs more than once in the array (if it does, they will be different), and if so, it is not the unique value. Use filter to process the array:
let array = [2,2,2,5];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [5,3,3,3,3];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
array = [4,4,5,4];
console.log(array.filter(v => array.indexOf(v) === array.lastIndexOf(v)));
You can create a recursive function that will take the first element of the array and see if it exists in the rest of it, if it does, it will take the next element and do the same, return the element if it doesn't exist in the rest of the array :
const arr = [3, 3, 3, 5, 3];
const find = arr => {
const [f, ...rest] = arr;
if(rest.includes(f))
return find(rest);
else
return f;
}
const result = find(arr);
console.log(result);
Note that this will return the last element if all of them are the same [3,3,3] will return 3
Try something like this using a set, which only stores unique elements:
var set = new Set(arr);
// count instances of each element in set
result = {};
for(var i = 0; i < a.length; ++i) {
if(!result[arr[i]])
result[arr[i]] = 0;
++result[arr[i]];
}
for (var value in result) {
if (value == 1) {
return value;
}
}
// if there isn't any
return false;
This should work, please tell me if it doesn't.
This is another implementation that is surely less efficient than that of #Nick's, but it is a valid algorithm anyway:
function findUniq(arr) {
var elemCount = new Map();
var uniq = [];
// Initialize elements conts
for (var k of arr.values()) {
elemCount.set(k, 0);
}
// Count elements
for (var k of arr.values()) {
elemCount.set(k, elemCount.get(k) + 1);
}
// Add uniq elements to array
for (var [k, v] of elemCount.entries()) {
if (v === 1) uniq.push(k);
}
return uniq;
}
console.log(findUniq([3, 5, 3, 3, 3]))
if you prefer .reduce over .map for your use case (for performance/etc. reasons):
function existance(data) {
return data.reduce((a, c) => (data.indexOf(c) === data.lastIndexOf(c)) ? a.concat(c) : a, []);
}
console.log(existance([1,1,1,2]));
console.log(existance([1,1,2,3,4,5,5,6,6,6]));

Comparing arguments with an arguments in JavaScript

Please help me with this code; I am trying to compare arguments with an array elements and return when it matches, I don't know what is wrong with this code, it returns 1 rather than an array , thanks.
const removeFromArray = function() {
var delArgs = [] ;
//convert the arguments to an array called 'args'.
var args = Array.from(arguments);
var Arr = args[0];
//using foreach() and forloop to compare arguments with Arr elements.
Arr.forEach(function(x){
for (var j=1 ; j < args.length ; j++){
if(x == args[j]){
delArgs = delArgs.push(x);
}
}
});
return delArgs;
}
removeFromArray([1,2,3,4,5,6] , 5);
1
delArgs = delArgs.push(x);
You're overwriting delArgs with the return value from push, which is the new length of the array.
Don't do that.
since the question is already answered, you could use this for shorter code
const removeFromArray = (array, ...args) => {
return args.filter( arg => array.includes(arg) )
}
console.log(removeFromArray([1, 2, 3, 4, 5, 6], 5,6));

Negating Callback Function Return Value

Straightforward question:
Can I negate a callback function that returns true or false o an array.filter() statement? e.g.
//the callback function
function isEven(element, index, array){
if (index%2 == 0 || index == 0){
return true;
}
return false;
}
//what i want to do with that function
//arr[i] is a string
var evens = arr[i].split("").filter(isEven); //works
var odds = arr[i].split("").filter(!isEven); // doesn't work
the above line gives me the error TypeError: false is not a function
Question with some background:
I'm taking on some Hackerrank challenges and i've come across an exercise that requires to take a string and process it, so the output is: The characters with even index values make a new string and the characters in odd index positions make another string , 0 counts as even.
Input
airplane
Output
evens = 'arln'
odds = 'ipae'
I have already solved it by looping through the string, evaluating the index and then pushing the value to the correspondent new array (which i later convert to a string), but it has occurred to me i could be done in a more functional way, using the Array.prototype.filter() function.
now I create a new function that evaluates whether the index number is even or not, and I'd like to use that same function to fill both arrays (evens and odds), like this (now you can refer to the straightforward question part):
var evens = arr[i].split("").filter(isEven); //works
var odds = arr[i].split("").filter(!isEven); // doesn't work
The simplest way to do this would be to just pass an anonymous function which returns the negated result of isEven.
var evens = arr[i].split("").filter(function(el, index, array) {
return !isEven(el, index, array);
});
But you could take this a step further and write a not function which essentially generates the anonymous function for you. Here's an example of such a function.
var input = [0, 1, 2, 3, 4, 5];
function isEven(value) {
return value % 2 === 0;
}
function not(f) {
return function() {
return !f.apply(null, arguments);
}
}
var output = input.filter(not(isEven));
console.log(output);
If you're in an environment that supports rest parameters then you could write your not function like this.
var input = [0, 1, 2, 3, 4, 5];
function isEven(value) {
return value % 2 === 0;
}
function not(f) {
return function(...args) {
return !f.apply(null, args);
}
}
var output = input.filter(not(isEven));
console.log(output);
You would need to pass in an anonymous function and then negate isEven in there:
var odds = arr[i].split("").filter(function(a, index, array) {
return !isEven(a, index, array);
});
Simple Example:
Working Example
function isEven(n) {
return n % 2 === 0;
}
var arr = [0,1,2,3,4,5,6,7,8,9];
var a = arr.filter(isEven);
var b = arr.filter(function(a) {
return !isEven(a);
});
The solution I use is something like this:
var numbers = [0,1,2,3,4,5];
var evens = [];
var odds = [];
function isEvenOrNot(getEven) {
return function(num) {
if (num % 2 == 0 || num == 0){
return true;
}
return false;
}
}
evens = numbers.filter(isEvenOrNot(true));
odds = numbers.filter(isEvenOrNot(false));
console.log(evens); // [0,2,4]
console.log(odds); // [1,3,5]

recursively putting array elements in their own array

I'm trying to create a function that puts each array element in its own array, recursively.
I think my base case is correct, but my recursive call doesn't appear to be working. any insight?
function ownList(arr){
if (arr.length === 1) {
arr[0] = [arr[0]];
return;
} else {
return arr[0].concat(ownList(arr.slice(1)));
}
}
var arr = [1,2,3]
console.log(ownList(arr))// returns []
//should return [[1],[2],[3]]
Here I'm trying to put each pair in it's own list (recursive only). This code below is correct (update)
function ownListPair(arr){
if (arr.length === 0)
return arr;
else if(arr.length === 1)
return [[arr[0], 0]];
else
return [[arr[0], arr[1]]].concat(ownListPair(arr.slice(2)));
}
// var arr = [3,6,8,1,5]
var arr = [2,7,8,3,1,4]
//returns [ [ 2, 7 ], [ 8, 3 ], [ 1, 4 ]]
console.log(ownListPair(arr))
I prefer this solution for several reasons:
function ownList(a) {
return a.length == 0
? []
: [[a[0]]].concat(ownList(a.slice(1)))
}
It's shorter and more concise
It works for empty arrays as well
The actual wrapping happens only once in the last line. Treating length == 1 separately -- as suggested by others -- is not necessary.
It would more appropriate to make a length of 0 be the null case. Then you just have to get the brackets right. The thing on the left side of the concat should be an array consisting of the array containing the first element.
function ownList(arr) {
return arr.length ? [[arr[0]]].concat(ownList(arr.slice(1))) : [];
}
Here's an alternative, take your pick:
function ownList(arr) {
return arr.length ? [[arr.shift()]] . concat(ownList(arr)) : [];
}
Using a bit of ES6 magic for readability:
function ownList([head, ...tail]) {
return head === undefined ? [] : [[head]] . concat(ownList(tail));
}
Here the [head, ...tail] is using parameter destructuring which pulls the argument apart into its first element (head) and an array of remaining ones (tail).
Instead of concat you could also use the array constructor:
function ownList([head, ...tail]) {
return head === undefined ? [] : Array([head], ...ownList(tail));
}
I think your basic assumption is wrong. What you need to do is check if each item in the array is an array, if not just add the item to the new array, if so have the function run itself on the array item.
That is recursion.
This code does that kind of recursion...
function ownList(arr)
{
var newArr = [];
var length = arr.length;
for (var i = 0; i < length; i++) {
if (typeof(arr[i]) === 'object') {
newArr.push(ownList(arr[i]));
continue;
}
newArr.push([arr[i]]);
}
return newArr;
}
var arr = [1, 2, 3];
console.log(ownList(arr));
Would something like this work:
var arr = [1, 2, 3, ["a", "b", "c", ["str"]]],
result = [];
function flatten(input){
input.forEach(function(el){
if(Array.isArray(el)){
flatten(el)
}else{
result.push([el]);
}
});
}
flatten(arr);
console.log(JSON.stringify(result));
//[[1],[2],[3],["a"],["b"],["c"],["str"]]
JSBIN
Edit:
var result = [];
function flatten(input){
if (input.length === 0){
console.log( "result", result ); //[[1],[2],[3],["a"],["b"],["c"],["str"]]
return;
}
//if zeroth el of input !array, push to result
if (!Array.isArray(input[0])){
result.push(input.splice(0, 1));
flatten(input);
}else{
flatten(input[0]); //else, give input[0] back to flatten
}
}
window.onload = function(){
var arr = [1, 2, 3, ["a", "b", "c", ["str"]]];
flatten(arr);
}
JSBIN
After struggling through this today, turns out that this works :)
function ownList(arr){
//base case:
if (arr.length === 1) {
return [arr];
}
//recurse
//have to do two brackets here --> (arr.slice(0,1)) since length > 1
return [arr.slice(0,1)].concat(ownList(arr.slice(1)));
}
var arr = [1,2,3]
console.log(ownList(arr))// returns [[1],[2],[3]]

Drop last element of javascript array when array reaches specific length

I would like to cache some data in javascript, but the cache should be limited to 10 elements for example.
I can place the objects in javascript array, but what is the best way to keep the array limited to 10 elements?
Example:
function getData(dataId) { return new NextDataObject(dataId); }
var array = new Array();
array.push(getData(0));
array.push(getData(1));
(...)
array.push(getData(10)); // this should result in dropping "oldest" data, so getData(0) should be removed from the array, so that in array there are only 10 objects at maximum
Should such mechanism be written manually (using splice() for example?) or are there better ways to achieve such "cache" structure in javascript?
BTW: in this particular situation I'm using angular.
Override the push function of your caching array.
var array = new Array()
array.push = function (){
if (this.length >= 10) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
Plunker
To make this more reusable I created a method which returns new instance of such array (basing on above code).
function getArrayWithLimitedLength(length) {
var array = new Array();
array.push = function () {
if (this.length >= length) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
return array;
}
var array = getArrayWithLimitedLength(10);
To remove first element from array use shift:
if (arr.length > 10) {
arr.shift(); // removes the first element from an array
}
How about this object?
function Cache(maxLength) {
this.values = [];
this.store = function(data) {
if(this.values.length >= maxLength) {
this.getLast();
}
return this.values.push(data);
}
this.getLast = function() {
return this.values.splice(0,1)[0];
}
}
cache = new Cache(3);
// => Cache {values: Array[0]}
cache.store(1)
// => 1
cache.store(2)
// =>2
cache.store(3)
// => 3
cache.store(4)
// =>3
cache.values
// => [2, 3, 4]
cache.getLast()
// => 2
cache.values
[3, 4]
You could create new method in Array.prototype to mimic your needs.
Array.prototype.push_with_limit = function(element, limit){
var limit = limit || 10;
var length = this.length;
if( length == limit ){
this.shift();
}
this.push(element);
}
var arr = []
arr.push_with_limit(4); // [4]
arr.push_with_limit(9); // [4, 9]
....
// 11th element
arr.push_with_limit(3); // [9, ..., 3] 10 elements
Simple fixed length queue:
Array.prototype.qpush = function( vals, fixed ) {
if (arguments.length) {
if (Array.isArray(vals)) {
for (var v of vals) {
this.push(v);
}
} else {
this.push(vals);
}
var _f = (typeof this.fixed != undefined) ? this.fixed : 0;
if (typeof fixed != undefined) {
_f = (Number(fixed)===fixed && fixed%1===0 ) ? fixed : _f;
}
this.fixed = _f;
if (this.fixed>0) this.splice(0, this.length - _f);
}
}
var q = new Array();
q.push(0);
q.qpush( [1, 2, 3], 10 );
q.qpush( [4] );
q.qpush( 5 );
q.qpush( [6, 7, 8, 9, 10, {k:"object"} ] );
console.log(q);
if(array.length == 10) {
array.splice(0, 1);
// this will delete first element in array
}
If you do a check whether the array has reached 10 entries with array.length, just remove the first element before pushing a new element. This can be done several ways as Tushar states, array.shift() would be the fastest, but you can indeed use array.splice() aswell.
It would look like this:
if(array.length > 10) {
array.shift();
array.push(getData(10));
}
On a side note, instead of using var array = new Array() I suggest you simply use var array = [];. This is because the new keyword in Javascript sometimes has bad side effects. If you for example want to create an array with 1 element being a digit, and you use var arr = new Array(12);, an array with 12 undefined elements will be created. Whereas var arr = [12]; will create an array with 1 element, the digit 12.
But I guess that's a minor thing to consider..
You could use an object instead...
var obj = {}; //your cache object
obj[window.performance.now()] = getData(val); //add value, index by microsecond timestamp
if(Object.keys(obj).length > 10){ // then if the length ever gets bigger than 10..
var array = Object.keys(obj).sort(); //sort the properties by microsecond asc
delete obj[array[0]]; //delete the oldest one
}
Here is a jsFiddle example showing how it works: https://jsfiddle.net/uhkvk4mw/
just check if the length is reached then pop it
if(arr.length > someNumber){
arr.pop(); // pop() will remove the last element
}

Categories