I have an array with boolean values:
var array = [false, false, false];
I want to execute a function only if all the elements are false.
I tried this and it didn't work, because it would execute the function for every false:
for(var i = 0; i < array.length; i++){
if(array[i] === false){
functionA(); //This function ran at every false
}else{
//Do something else
}
}
if (array.indexOf(true) == -1) {
functionA();
}
The indexOf function returns the first index at which a given element can be found in the array, or -1 if it is not present.
You could do something like:
function checkAllSameValue(array) {
var identical = true;
var i = 0;
while ((i + 1) in array && identical) {
identical = array[i] == array[++i];
}
return identical;
}
Which checks if each member is identical to the next
Edit
In response to ilia choly's issues with performance and lookups, here's an alternative that is as fast as a for loop, perhaps faster depending on the UA:
function checkAllSameValue(array) {
var i = array.length;
var value = array[--i];
while (i) {
if (arr[--i] != value) return false
}
return true;
}
Whether == or === should be used is up to the OP. None of the posted solutions deals with sparse arrays, so none are general solutions.
Gues this will help:
var array = [false, false, false];
var flag = true;
for(var i = 0; i < array.length; i++){
if(array[i]!= false){
flag = false;
break;
}
}
if(flag){
functionA(); //This function call function only once
}
The way you describe it is slightly different from the title. If you're only trying to execute the function if they are all false, then Steve's answer is great. Depending on where this array comes from, I would probably expand it like so, though, to be defensive about it:
if (array.indexOf(true) == -1 && array.indexOf(null) == -1) {
functionA();
}
OTOH, if you want to run it any time they are all the same, then you'll need more complex logic.
In that case, I would probably set a flag, update it in the loop, and then do the function call after the loop. You'll also need a variable to keep track of the previous value. If any value doesn't match its previous value, they're not all the same, so you set the flag to false. Then, after the loop, you check the flag and run the function if it's true.
Something like this:
var runFunction = true;
var previousVal = -1;
for (var i = 0; i < array.length; i++){
if(previousVal === -1) {
previousVal = array[i];
}
if(array[i] !== previousVal){
runFunction = false;
break;
}
}
if (runFunction) {
functionA();
} else {
// Do something else
}
Steve's way is better, but if you were going to use your approach it would be
var allFalse = true, i;
for(i = 0; i < array.length; i++) {
if(array[i]){
allFalse = false;
break;
}
}
if (allFalse) {
functionA();
}
or
if (array.every(function(val) { return !val; })) {
functionA();
}
if you want a generic function to check if all elements are the same you can do this
function checkAllSameValue(array) {
var first = array[0], i;
for (i = 1; i < array.length; i++) {
if (array[i] !== first) return false;
}
return true;
}
Related
The tests return true, but fails to return false. Could someone please explain me why?
function isItemOmnipresent(arrayOfArrays, item) {
for (let i = 0; i < arrayOfArrays.length; i++) {
for (let j = 0; i < arrayOfArrays[i].length; j++) {
if (arrayOfArrays[i][j] === item) {
return true;
}
}
}
return false;
}
Since the function will end when the interpreter comes across a return, you should only return once the whole array fails the tests. Tweaking your for loop method, check a flag that gets set when a matching item is found:
function isItemOmnipresent(arrayOfArrays, item) {
for (let i = 0; i < arrayOfArrays.length; i++) {
let found = false;
for (let j = 0; i < arrayOfArrays[i].length; j++) {
if (arrayOfArrays[i][j] === item) {
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
Hint: return ends the function. So if the item is present in at least one of the Arrays, it returns true.
You could do it like this:
function isItemOmnipresent(arrayOfArrays, item) {
return arrayOfArrays.every(arr => arr.includes(item));
}
function confirmEnding(str, target) {
var end = target;
var match = '';
for(var x = 0; x < str.length; x++){
for(var j = 0; j < str[x].length; j++){
if(str[x][j]){
match = str[x][j];
}
}
}
return match.substr(-target.length) === target;
}
confirmEnding("He has to give me a new name", "name");
but I want to know if I can instead loop through the string and then check it using the appropriate indexes.
Can someone understand my approach and let me know how/why it's not doable?
It's currently only checking for the last character, so whole words aren't working. I know the line below will work
return str.substr(-target.length) === target;
will work, but can someone help me with my approach
Edit:
I changed it more slightly, and got closer but still no luck.
function confirmEnding(str, target) {
for(var x = str.length-1; x < str.length; x++){
for(var j = target.length-1; j>=0; j--){
if(str[x] === target[j]){
return true;
} else{
return false;
}
}
}
}
confirmEnding("Walking on water and developing software from a specification are easy if both are frozen", "specification");
That returns true, when it should return false. I see why, but thinking of a resolve.
If using the loop is a strict requirement, then I would do it in a way
function confirmEnding(source, target) {
var lengthT = target.length;
var lengthS = source.length;
for(var x = 0; x < lengthT; x++) {
if(source[lengthS - 1 - x] !== target[lengthT - 1 - x]) {
return false;
}
}
return true;
}
confirmEnding("He has to give me a new name", "name"); // true
But the easier implementation of confirmEnding method would be just
function confirmEnding(source, target) {
return source.substr(source.length - target.length, target.length) === target;
}
I'm trying to write a recursive function to locate a value within a multidimensional array. Here's what I've tried so far:
var locate = function (arr,value) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === value) {
return true;
} else if (Array.isArray(arr[i])) {
locate(arr[i], value);
}
}
return false;
}
However, it isn't working:
console.log(locate(['a','b',['c','d',['e']]],'e'))
// => returns `false`, but should return `true`
How should I approach this problem?
Here's a recursive DFS:
var locate = function (arr, value) {
// start at the current array; we want to check every value
for (var i = 0; i < arr.length; i++) {
// if we've found our value, return immediately
if (arr[i] === value) {
return true;
// if the element is an array, call locate on the element
// and possibly return true
// we don't want to return locate(arr[i], value) because
// it could be found later on
} else if (Array.isArray(arr[i]) && locate(arr[i], value)) {
return true;
}
}
// reached the end of the current array, so return `false`
// note, since we use `else if (... locate(arr[i], value)),
// we won't stop the recursion before checking every possible value
return false;
}
Even if one of the nested calls to locate() returns true, you're just throwing that value away.
var locate = function(haystack, needle) {
for (var i = 0; i < haystack.length; i++) {
if (Array.isArray(haystack[i])) {
if (locate(haystack[i], needle)) {
return true;
}
} else if (haystack[i] === needle) {
return true;
}
}
return false;
}
var locate = function(arr,value){
for (var i = 0; i < arr.length; i++) {
if (arr[i] === value) {
return true;
}
else if (Array.isArray(arr[i])) {
var value = locate(arr[i], value);
if(value === true){
return true;
}
}
}
return false;
}
console.log(locate(['a','b',['c','d',['e']]],'e'))
It is not that your recursion was off.
It was that you ignored the return value and eventually returned false either way.
So you need to return the result of the recursion in case you recurse.
What would be a shorter way to write :
if (array1[0] >= array2[0] && array1[1] >= array2[1] && ...) {
do something;
}
I tried creating a function but I was not able to make it work, I'm still quite new at this.
The most elegant way would be to use .every
The every() method tests whether all elements in the array pass the test implemented by the provided function.
if (array1.every(function(e,i){ return e>=array2[i];})) {
do something;
}
This will return true if all elements of a are greater than all elements of b. It will return as early as possible rather than having to compare all of the elements.
function compare(a, b) {
for (i = 0; i < a.length; i++) {
if (a[i] < b[i]) { return false;}
}
return true
}
var isGreater = true;
for (var i = 0; i < array1.length; i++)
{
if (array1[i] < array2[i])
{
isGreater = false;
break;
}
}
if (isGreater)
{
//do something
}
You loop your first array and replace the numbers by the looping variable (i)
I am trying to determine if ANY value from one array matches ANY value from another array. The problem that i am having is that if there are two values in my array and the first value is found but the second is not found, my indicator is coming up as FALSE when i need it to return TRUE. Here is some example code that i'm working with:
var itemArray = ['apples','bananas','cherries'];
var categoryArray = ['donuts','cherries','eclairs','fruit','grapes'];
for(var z=0; z<itemArray.length; z++){
for(var y=0; y<categoryArray.length; y++){
if(itemArray[z] == categoryArray[y]) var isInArray = true;
else var isInArray = false;
}
}
alert(isInArray);
Appreciate the help, let me know if more information is needed.
You need to break or return once you've found a value that matches. Otherwise, the else case overwrites isInArray if it was already true. Alternately, initialize isInArray to false, and only assign it to true in the loop. Here's how I'd do it:
function isInArray(itemArray, categoryArray) {
for(var z=0; z<itemArray.length; z++) {
for(var y=0; y<categoryArray.length; y++) {
if(itemArray[z] == categoryArray[y]) return true;
}
}
return false;
}
I prefer early return in cases such as this.
You could also simplify it a bit using indexOf:
var itemArray = ['apples','bananas','cherries'];
var categoryArray = ['donuts','cherries','eclairs','fruit','grapes'];
var isInArray = false;
for(var z=0; z<itemArray.length; z++){
if( categoryArray.indexOf(itemArray[z]) !== -1) {
isInArray = true;
break;
}
}
alert(isInArray);