I want to check if an array contains an array of values rather then a value, for example
var arr = [1, 2, 3];
arr.contains([1, 2]); // returns true
// and
arr.contains([1, 5]); // must be false
There is a method called contains in underscore _.contains but it works like .indexof() in javascript instead it returns true and false and only find a value and not an array
Also there is a method Array.prototype.includes() in javascript that also take single input rather of an array
actually I want to check if second array has all the keys present in
first array I want to check with AND
for example [1,2,3,4].contains([1,4]) must return true where as [1,2,3,4].contains([1,9]) must return false, hope this makes sense,
I'm for now using underscores intersection and second array with
intersection result it must be same, its still long procedure....
You could use Array.prototype.includes() within a for loop
var arr = [1,2,3,4];
function contains(arr) {
for (var i = 0, included = true; i < arr.length
; included = included && this.includes(arr[i]), i++);
return included
}
Array.prototype.contains = contains;
console.log(arr.contains([1, 4]), arr.contains([9, 1]), arr.contains([1, 5]))
You can use a combination of every and indexOf
[1, 2].every(function(e) { return [1, 2, 3].indexOf(e) !== -1 });
would evaluate to true and
[1, 5].every(function(e) { return [1, 2, 3].indexOf(e) !== -1 });
would evaluate to false
The syntax would be a lot shorter in ES6 with arrow functions
[1, 2].every(e => [1, 2, 3].indexOf(e) !== -1)
Try this simple example
var arr = [1, 2, 3];
var searchArr = [1,2];
var isSearchArrAvailable = searchArr.filter( function(value){ if ( arr.indexOf( value ) == -1 ) { return true } else { return false; } } ).length == 0;
console.log( "is SearchArr Available " + isSearchArrAvailable );//this will print true
while var searchArr = [1,5] will print false.
You can refactor it into a function
function hasEveryElement(arr, searchArr)
{
return searchArr.filter( function(value){ if ( arr.indexOf( value ) == -1 ) { return true } else { return false; } } ).length == 0;
}
console.log( hasEveryElement([1,2,3], [1,2]) ) ;
console.log( hasEveryElement([1,2,3], [1,4]) ) ;
You can use every:
function contains(arr, arr2) {
return arr2.every(function (el) {
return arr.indexOf(el) > -1;
});
}
var arr = [1, 2, 3];
contains(arr, [1, 2]); // true
contains(arr, [1, 5]); // false
Alternatively, you could add a method to the prototype if you wanted the [].includes-style syntax, but call it something else - I've used hasAll.
if (!('hasAll' in Array.prototype)) {
Array.prototype.hasAll = function(arr) {
return arr.every(function(el) {
return this.indexOf(el) > -1;
}, this);
}
arr.hasAll([1, 2])); // true
arr.hasAll([1, 5])); // false
DEMO
Try this:
var arr = [1,2,3];
var temparr=[1,2];
var st=ArrOfArrSt(arr,temparr);
function ArrOfArrSt(arr,temparr){
var stArr= new Array();
if(temparr.length>0)
for(j in temparr){
if(arr.indexOf(temparr[j])==-1){
stArr.push('0');
}
}
return (stArr.length>0)?0:1; //whole array 0=not belong to / 1=belong to
}
Related
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);
I want to attach a new method to the Array.prototype:
Array.prototype.uniq = function(){
return this.filter((val, index) => {
return this.indexOf(val) === index;
});
};
var a = [1, 1, 2, 3];
console.log(a.uniq()); // output: [1,2,3]
console.log(a); // output: [1,1,2,3]
The method removes duplicates from an array. The problem I have is that whenever uniq is called, a new array is returned. I want to do something like this:
Array.prototype.uniq = function(){
this = this.filter((val, index) => { // "ReferenceError: Invalid left-hand side in assignment
return this.indexOf(val) === index;
});
};
so that:
var a = [1, 1, 2, 3];
a.uniq();
console.log(a); // output: [1,2,3]
What should I do?
You can iterate over the array using for loop and use splice if the index are not same.
Array.prototype.uniq = function () {
// Reverse iterate
for (var i = this.length - 1; i >= 0; i--) {
// If duplicate
if (this.indexOf(this[i]) !== i) {
// Remove from array
this.splice(i, 1);
}
}
// Return updated array
return this;
};
var a = [1, 1, 2, 3];
a.uniq();
console.log(a); // output: [1,2,3]
I tried to remove some words according to the passing variable.
However, I wrote two versions of code which have minor different!
And they resulted in different kinds of output which I don't understand why!
So I need u guys help, and big big thanks for u guys!
This function will be accepting the different numbers of variables,
which might be ( [arr],1,2 ) or ( [arr],1,2,8,9...) etc,
and remove the the variable in the first array according to the passing numbers.
For example: destroyer ( [1, 2, 3, 4], 2, 3 ) --> output should be [1,4]
And here is my code. ( Notice the minor difference with bold fonts! )
function destroyer(arr) {
for ( var i = 1; i < arguments.length; i++ ){
arr = arguments[0].filter(function(value){
if( value == arguments[i]){
return false;
}else{
return true;
}
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
The output will be [1,2,3,1,2,3], which means value == arguments[i] doesn't work. However,
function destroyer(arr) {
for ( var i = 1; i < arguments.length; i++ ){
filter = arguments[i];
arr = arguments[0].filter(function(value){
if( value == filter){
return false;
}else{
return true;
}
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
This version works perfectly showing me [1,1].
So what's going wrong with the first version??? Thank you!!
The problem with the first one is that arguments applies to the .filter() callback function (the closest function scope, not the parent function scope) so arguments[i] is not what you want it to be.
You could copy those arguments into an actual array which you could then refer to from the .filter() callback.
function destroyer(arr) {
var args = [].slice.call(arguments, 1);
for ( var i = 0; i < args.length; i++ ){
arr = arr.filter(function(value){
if( value == args[i]){
return false;
}else{
return true;
}
});
}
return arr;
}
var a = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
// show output
document.write(JSON.stringify(a));
Personally, I'd suggest a bit simpler version:
function destroyer(arr) {
var args = [].slice.call(arguments, 1);
return arr.filter(function(value) {
return args.indexOf(value) === -1;
});
}
var a = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
// show output
document.write(JSON.stringify(a));
Which, can be written simpler in ES6 using the spread operator:
function destroyer(arr, ...args) {
return arr.filter(function(value) {
return args.indexOf(value) === -1;
});
}
var a = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
// show output
document.write(JSON.stringify(a));
Or, if you prefer even shorter ES6 notation and want to use the new Array.prototype.includes():
function destroyer(arr, ...args) {
return arr.filter(value => !args.includes(value));
}
var a = destroyer([1, 2, 3, 1, 2, 3], 2, 3);
document.write(JSON.stringify(a));
I would write it like that in an es6 version:
function destroyer( arr, ...elem ) {
return arr.reduce( ( prev, next, index ) => elem.includes( arr[index] ) ? prev : prev.concat(next) , [])
}
so i am trying to compare 2 arrays to see if their contents are the same, see example below
var array1 = [0,2,2,2,1]
var array2 = [0,2,2,2,3]
i want to compare those 2 arrays using the some method
so i will write a function that returns true if some of the numbers are in both arrays.
i have used the method perfectly fine on one array trying to find a particular value
function testArray(){
var bool = array1.some(function(value){
return value ===1;
});
}
console.log(bool)
but how to use it for 2 arrays? any help is appreciated
A solution with Array.prototype.every()
The every() method tests whether all elements in the array pass the test implemented by the provided function.
and Array.prototype.some()
The some() method tests whether some element in the array passes the test implemented by the provided function.
for the same task. Please watch the bangs!
var array1 = [0, 2, 2, 2, 1],
array2 = [0, 2, 2, 2, 3];
function compareEvery(a1, a2) {
if (a1.length !== a2.length) { return false; }
return a1.every(function (a, i) {
return a === a2[i];
});
}
function compareSome(a1, a2) {
if (a1.length !== a2.length) { return false; }
return !a1.some(function (a, i) {
return a !== a2[i];
});
}
document.write(compareEvery(array1, array2) + '<br>');
document.write(compareEvery(array1, array1) + '<br>');
document.write(compareSome(array1, array2) + '<br>');
document.write(compareSome(array1, array1) + '<br>');
You could use this approach
function compare(arr1, arr2) {
if (arr1.length != arr2.length) return false;
for (var i = 0; i < arr2.length; i++) {
if (arr1[i].compare) {
if (!arr1[i].compare(arr2[i])) return false;
}
if (arr1[i] !== arr2[i]) return false;
}
return true;
}
var array1 = [0, 2, 2, 2, 1];
var array2 = [0, 2, 2, 2, 3];
compare(array1, array2);
If you want to test if two arrays contains the same value, you can use some in combination with indexOf:
function containsSameValue(arr1, arr2) {
return arr1.some(function(value) {
return arr2.indexOf(value) > -1;
});
}
var array1 = [0, 2, 2, 2, 1];
var array2 = [0, 2, 2, 2, 3];
containsSameValue(array1, array2); // true
containsSameValue([1, 2, 3], [4, 5, 6]); // false
I need a function that would return a value from an array that may contain any number of arrays. It should be called like getValueFromArray(array, [2, 4]) - this example should return 4th element of the 2d array of the passed array.
Here is my code:
function getValueFromArray(arr, indexes){
var val,
currentIndex = indexes[0];
if(!arr[currentIndex] || arr[currentIndex] === '') return value = '';
indexes.splice(0, 1);
if(arr[currentIndex].length)
getValueFromArray(arr[currentIndex], indexes);
else {
val = arr[currentIndex];
return val;
}
}
var y = getValueFromArray([[1,2,3,4], [1,2,3,4]], [0, 2]); // should return 3
var x = getValueFromArray([[1,2,3,4], [1,2,3,4], [5,6,7,8]], [2, 3]); // should return 8
var z = getValueFromArray(
[
[[1,2,3,4], [1,2,3,4], [1,2,3,4]],
[[1,2,3,4], [1,2,3,4]]
],
[0, 1, 2]
); // should return 3
Such call should return 3, and if I debug the function, it actually returns the correct value but when I assign it to a variable, it returns undefined. I guess it's because of the recursion, variable gets the value that is undefined during the first function call. How can this be fixed?
Thank you!
You are not returning your recursive results.
if(arr[currentIndex].length)
getValueFromArray(arr[currentIndex], indexes);
Should be:
if(arr[currentIndex].length)
return getValueFromArray(arr[currentIndex], indexes);
you missed one thing in your code(returning the result after if condition) try below given code:-
function getValueFromArray(arr, indexes){
var val,
currentIndex = indexes[0];
if(!arr[currentIndex] || arr[currentIndex] === '') return value = '';
indexes.splice(0, 1);
if(arr[currentIndex].length)
return getValueFromArray(arr[currentIndex], indexes);
else {
val = arr[currentIndex];
return val;
}
}
var y = getValueFromArray([[1,2,3,4], [1,2,3,4]], [0, 2]);
console.log(y)
run it and see, now its showing the result into the variable.
I think you need to add a return before
getValueFromArray(arr[currentIndex], indexes);
To make the final calculated value to recurse up the recursive method call stack as each recursed call returns.
Your guess is correct. You simply forgot to return whatever the recursive call returns:
if(arr[currentIndex].length)
getValueFromArray(arr[currentIndex], indexes); // <---- here
That being said, I have to agree that you could easily do it more concisely (this will eventually destroy indexes, however):
function getValueFromArray(arr, indexes){
while(indexes.length) arr=arr[indexes.shift()]
return arr
}
It's because if condition is not returning any value.
Try following code
function getValueFromArray(arr, indexes){
var val='',currentIndex = indexes[0];
if(!arr[currentIndex] || arr[currentIndex] === '') return val;
indexes.splice(0, 1);
if(arr[currentIndex].length) {
// Because if your function walks this way
// it does not meet any 'return' statement
// till the end and returns nothing.
return getValueFromArray(arr[currentIndex], indexes);
}
else {
val = arr[currentIndex];
return val;
}
}
Then console log you variable
var y = getValueFromArray([[1,2,3,4], [1,2,3,4]], [0, 2]);
console.log(y)
I'll post my code too as I feel it provides a simpler solution to your problem.
There is no recursion involved, so it should run a bit faster in theory.
var arr = [
[
[
[12, 5, 6],
[ 6, 7, 8],
[11, 0, 9]
],
[
[-1, 1, 8],
[ 4, 5, 6]
]
],
[
[
[7, 8, 9, 10]
]
]
];
function getValueFromArray(arr, indexes){
var value = arr, i = 0, len = indexes.length, index = null;
for (; i < len; i += 1) {
index = indexes[i];
// check if the current array contains an {index}-th record
if ( index in value ) {
value = value[index];
} else {
// or throw an exception if you want
return null;
}
}
return value;
}
getValueFromArray(arr, [0, 1, 1, 2]) // 6
function getValueFromArray(arr, indexes) {
// exit if arr is not an array
// exit if arr is empty
// exit if indexes is not an array
// exit if indexes is empty
if (!Array.isArray(arr) || !arr.length || !Array.isArray(indexes) || !indexes.length) {
return; // may throw exception or return other value
}
var currentIndex = indexes.shift();
// exit if index is not in arr
// exit if index is negative
if (arr.length <= currentIndex || currentIndex < 0) {
return; // may throw exception or return other value
}
return Array.isArray(arr[currentIndex]) ? getValueFromArray(arr[currentIndex], indexes) : arr[currentIndex];
}
You are overthinking this:
function getValueFromArray(arr, indexes){
return arr[indexes[0]][indexes[1]];
}
EDIT for 1 to 3 dimensional array:
function getValueFromArray(arr, indexes){
if (indexes.length == 1) {
return arr[indexes[0]];
} else if (indexes.length == 2) {
return arr[indexes[0][indexes[1]];
} else if (indexes.length == 3) {
return arr[indexes[0][indexes[1][indexes[2]];
} else {
// 4 dimensional arrays???
}
}
Would you have more than 3 dimensional array?
It would be best find a way to append indexes[i] but I can't think of a way at the moment and I don't think it's possible.