Function Iterations Inquiry - javascript

I have been given the task of creating a function that iterates through an array. Below is what I have, but I’m getting undefined. What am I missing?
function lookingForDave(arr) {
for (var i = 0; i < arr; i++) {
if (array.forEach === 'Dave') {
return 'I found him';
} else {
return 'Not Dave';
}
}
}
var testArray = ['Dave'];
console.log(lookingForDave(testArray));

You need to check an element of the array against a value, then return if found, otherwise return 'Not Dave' at the end of the function.
If you return at the first check of the value and return not found, you omit all other elements for checking.
function lookingForDave(array) {
for (var i = 0; i < array.length; i++) {
if (array[i] === 'Dave') {
return 'I found him';
}
}
return 'Not Dave';
}
var testArray = ['Dave'];
console.log(lookingForDave(testArray));
Another solution could be to use Array#includes and return the wanted string.
function lookingForDave(array) {
return array.includes('Dave')
? 'I found him'
: 'Not Dave';
}
var testArray = ['Dave'];
console.log(lookingForDave(testArray));

You could use find rather than a for loop. It looks as if you want to return after you first find a match. Array.find will return the value of the first matching criteria.
In the below case if the element in the array is equal to Dave. If there is no match then we will iterate through each item in the array and return undefined.
We can then use the conditional (ternary) operator to test if an item was found.
function lookingForDave (arr){
const found = arr.find(el => el === 'Dave');
return found ? 'found him' : 'Not Dave';
}
let testArray = ['Dave'];
lookingForDave(testArray);
conditional (ternary) operator
Array find

Here's yet another solution:
function lookingForDave(array) {
return array.some(el => el === "Dave") ?
"It's Dave" :
"Not Dave!";
}
var testArray = ["Dave", "Bob", "Sam"];
console.log(lookingForDave(testArray));
Here's hoe it works:
some() takes a function that is run for each and every element in your array. The function that you pass as an argument must return a truthy or falsy value.
If any of those return statements is truthy, some() returns true.
Using a the ternary operator we check if it's true we return "It's Dave" and otherwise "Not Dave!".
Hope that helps!

Related

indexOf gives false positives

I made a function to search words in a string given. The function called str_find receives the word and then the parameters to search. These parameters can be an array with strings or only a string.
For example, if I call the function like: str_find("123456789&", ["", "123456789&"]); it should give me true, but for a rare reason sometimes it gives me false.
Can you help me please?
My code:
function str_find(word, find){
if(!Array.isArray(find)){
if (word.indexOf(find) > 0) {
return true;
} else {
return false;
}
} else {
var flag = false;
for (var i = 0, length = find.length; i < length; i++) {
if (word.indexOf(find[i]) > 0) {
flag = true;
break;
}
}
return flag;
}
}
You can take advantage of both String and Array having an includes() prototype method
function str_find(needle, haystack) {
return haystack.includes(needle);
}
console.log(str_find("123456789&", ["", "123456789&"]))
console.log(str_find("foo", 'foobar'))
MDN points out the reason in an obscure way:
Return value
The value of the first element in the array that satisfies the
provided testing function. Otherwise, undefined is returned.
When the string is found at the very first position of the searched string, it returns a found location index of 0 - which is a falsy value:
Thus your logical test if (word.indexOf(find) > 0) returns false when this occurs and gives the false indication that the string was not found, when in fact it was found at the very beginning of the search string.
You can change this behavior by testing for -1 rather than > 0.
Alternatively, you can choose to use other Array methods that are less obscure.
const data = ["", "123456789&"];
const str = "123456789&";
const tests = ["4", "", "123456789&", ";", ["456", "123456789&"]];
function str_find(toFind, toSearch) {
let found = false;
if (!Array.isArray(toFind)) {
if (toSearch.indexOf(toFind) !== -1) {
found = true;
}
} else {
for (var i = 0; i < toFind.length; i++) {
found = str_find(toFind[i],toSearch);
}
}
return found;
}
tests.forEach(t=>console.log("test: ", t, str_find(t, data)));

Why does my for loop return the correct answer, but my forEach does not?

this is my first question on SO. I have an assignment where I'm supposed to create a function that has two parameters--the first being an array of strings, and the second being a string to possibly match in the array.
I have two variations of the function: one uses a "for" loop, the other uses the .forEach() method. The for loop accurately returns "true"/"false" depending on whether or not the second parameter exists within the array. The forEach always returns "false".
Can someone explain why? Code below:
.forEach() version:
function insideArray (array, word) {
var value;
array.forEach(function(each) {
if(each === word) {
value = "true";
return value;
}
else {
value = "false";
}
});
return value;
}
for loop version:
function insideArray (array, word) {
var value;
for(var i = 0; i < array.length; i++) {
if(array[i] === word) {
value = "true";
return value;
}
else {
value = "false";
}
}
return value;
}
A sample array:
var heroArray = [ "spiderman", "wolverine", "batman", "greenArrow", "boosterGold" ];
Testing .forEach():
insideArray(heroArray, "spiderman");
"false"
Testing for loop:
insideArray(heroArray, "spiderman");
"true"
Thanks for any help in advance!
This happens because you are returning from callback function of forEach and not from insideArray() so in the end insideArray() will always return false except in the case you match the last element in the array. you can fix the code by initializing value with false and removing else condition like this:
function insideArray (array, word) {
var value = "false";
array.forEach(function(each) {
if(each === word) {
value = "true";
}
});
return value;
}
Also note that you can write more simple code for this by using indexOf:
function insideArray (array, word) {
return array.indexOf(word) >= 0 ? "true" : "false";
}
The .forEach method doesn't return anything, so I'd modify your code to the following:
function insideArray (array, word) {
var value = "false";
array.forEach(function(each) {
if(each === word) {
value = "true";
}
});
return value
};
You can't break/return out of a Array#forEach loop, though you could throw and catch from it (but don't). Array#some would probably be a better choice, if you intend to test like that. A better, though slightly less well supported, method would be to use Array#includes (polyfills are available, or transpile with babel). Another solution would be Array#indexof
function insideArray(array, word) {
return String(array.some(function(each) {
return each === word;
}));
}
var heroArray = ['spiderman', 'wolverine', 'batman', 'greenArrow', 'boosterGold'];
console.log(insideArray(heroArray, 'supergirl'));
console.log(insideArray(heroArray, 'batman'));
const insideArray = (array, word) => String(array.includes(word));
const heroArray = ['spiderman', 'wolverine', 'batman', 'greenArrow', 'boosterGold'];
console.log(insideArray(heroArray, 'supergirl'));
console.log(insideArray(heroArray, 'batman'));

Find whether Value in Object exists within an array

I am trying to find whether the value roomTypeFilter exists within an Object inside an array. I then want to perform conditional statements depending whether the value roomTypeFilter exists or not.
Below is my code
function includes(k) {
for (var i = 0; i < this.length; i++) {
if (this[i] === k || (this[i] !== this[i] && k !== k)) {
return true;
}
}
return false;
}
var dayValue = this.ui.dayConstraintList.val();
var arr = [courseTemplate.get('dayConstraints')[dayValue]];
console.log(arr);
arr.includes = includes;
console.log(arr.includes('roomTypeFilter'));
The first console.log returns an Object inside an array.
The second console.log returns false, in this case as roomTypeFilter exists inside the Object I want to return 'true' but I am unsure how to do so, any help would be greatly appreciated.
Instead of using includes, use hasOwnProperty. Take a look here for more information on the hasOwnProperty. It's pretty self-explanatory from its name - it essentially returns a boolean on whether or not the object has a property. I.e., in your case, you would use:
arr[0].hasOwnProperty('roomTypeFilter');
You can use hasOwnProperty method to check if object contains roomTypeFilter property.
...
if (this[i].hasOwnProperty(k)) {
...
}
...
You could refactor your includes function to use
array.prototype.some
some() executes the callback function once for each element present in the array until it finds one where callback returns a truthy value... If such an element is found, some() immediately returns true.
Here is an example.
var arr = [
{
roomTypeFilter: {
name: 'foo'
}
},
["roomTypeFilter", "foo"],
"roomTypeFilter foo"
]
function includes(arr, k) {
return arr.some(function(item) {
return item === Object(item) && item.hasOwnProperty(k);
})
}
console.log("Does arr includes roomTypeFilter ? - ", includes(arr, 'roomTypeFilter'))

In Javascript, how do I check if an array has duplicate values?

Possible Duplicate:
Easiest way to find duplicate values in a javascript array
How do I check if an array has duplicate values?
If some elements in the array are the same, then return true. Otherwise, return false.
['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist
Notice I don't care about finding the duplication, only want Boolean result whether arrays contains duplications.
If you have an ES2015 environment (as of this writing: io.js, IE11, Chrome, Firefox, WebKit nightly), then the following will work, and will be fast (viz. O(n)):
function hasDuplicates(array) {
return (new Set(array)).size !== array.length;
}
If you only need string values in the array, the following will work:
function hasDuplicates(array) {
var valuesSoFar = Object.create(null);
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in valuesSoFar) {
return true;
}
valuesSoFar[value] = true;
}
return false;
}
We use a "hash table" valuesSoFar whose keys are the values we've seen in the array so far. We do a lookup using in to see if that value has been spotted already; if so, we bail out of the loop and return true.
If you need a function that works for more than just string values, the following will work, but isn't as performant; it's O(n2) instead of O(n).
function hasDuplicates(array) {
var valuesSoFar = [];
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (valuesSoFar.indexOf(value) !== -1) {
return true;
}
valuesSoFar.push(value);
}
return false;
}
The difference is simply that we use an array instead of a hash table for valuesSoFar, since JavaScript "hash tables" (i.e. objects) only have string keys. This means we lose the O(1) lookup time of in, instead getting an O(n) lookup time of indexOf.
You could use SET to remove duplicates and compare, If you copy the array into a set it will remove any duplicates. Then simply compare the length of the array to the size of the set.
function hasDuplicates(a) {
const noDups = new Set(a);
return a.length !== noDups.size;
}
One line solutions with ES6
const arr1 = ['hello','goodbye','hey']
const arr2 = ['hello','goodbye','hello']
const hasDuplicates = (arr) => arr.length !== new Set(arr).size;
console.log(hasDuplicates(arr1)) //return false because no duplicates exist
console.log(hasDuplicates(arr2)) //return true because duplicates exist
const s1 = ['hello','goodbye','hey'].some((e, i, arr) => arr.indexOf(e) !== i)
const s2 = ['hello','goodbye','hello'].some((e, i, arr) => arr.indexOf(e) !== i);
console.log(s1) //return false because no duplicates exist
console.log(s2) //return true because duplicates exist
Another approach (also for object/array elements within the array1) could be2:
function chkDuplicates(arr,justCheck){
var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
arrtmp.sort();
while(len--){
var val = arrtmp[len];
if (/nul|nan|infini/i.test(String(val))){
val = String(val);
}
if (tmp[JSON.stringify(val)]){
if (justCheck) {return true;}
dupes.push(val);
}
tmp[JSON.stringify(val)] = true;
}
return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true); //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true); //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true); //=> false
chkDuplicates([1,2,3,4,5,1,2]); //=> [1,2]
chkDuplicates([1,2,3,4,5]); //=> null
See also...
1 needs a browser that supports JSON, or a JSON library if not.
2 edit: function can now be used for simple check or to return an array of duplicate values
You can take benefit of indexOf and lastIndexOf. if both indexes are not same, you have duplicate.
function containsDuplicates(a) {
for (let i = 0; i < a.length; i++) {
if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
return true
}
}
return false
}
If you are dealing with simple values, you can use array.some() and indexOf()
for example let's say vals is ["b", "a", "a", "c"]
const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);
some() will return true if any expression returns true. Here we'll iterate values (from the index 0) and call the indexOf() that will return the index of the first occurrence of given item (or -1 if not in the array). If its id is smaller that the current one, there must be at least one same value before it. thus iteration 3 will return true as "a" (at index 2) is first found at index 1.
is just simple, you can use the Array.prototype.every function
function isUnique(arr) {
const isAllUniqueItems = input.every((value, index, arr) => {
return arr.indexOf(value) === index; //check if any duplicate value is in other index
});
return isAllUniqueItems;
}
One nice thing about solutions that use Set is O(1) performance on looking up existing items in a list, rather than having to loop back over it.
One nice thing about solutions that use Some is short-circuiting when the duplicate is found early, so you don't have to continue evaluating the rest of the array when the condition is already met.
One solution that combines both is to incrementally build a set, early terminate if the current element exists in the set, otherwise add it and move on to the next element.
const hasDuplicates = (arr) => {
let set = new Set()
return arr.some(el => {
if (set.has(el)) return true
set.add(el)
})
}
hasDuplicates(["a","b","b"]) // true
hasDuplicates(["a","b","c"]) // false
According to JSBench.me, should preform pretty well for the varried use cases. The set size approach is fastest with no dupes, and checking some + indexOf is fatest with a very early dupe, but this solution performs well in both scenarios, making it a good all-around implementation.
function hasAllUniqueChars( s ){
for(let c=0; c<s.length; c++){
for(let d=c+1; d<s.length; d++){
if((s[c]==s[d])){
return false;
}
}
}
return true;
}

How can I check JavaScript arrays for empty strings?

I need to check if array contains at least one empty elements. If any of the one element is empty then it will return false.
Example:
var my_arr = new Array();
my_arr[0] = "";
my_arr[1] = " hi ";
my_arr[2] = "";
The 0th and 2nd array elements are "empty".
You can check by looping through the array with a simple for, like this:
function NoneEmpty(arr) {
for(var i=0; i<arr.length; i++) {
if(arr[i] === "") return false;
}
return true;
}
You can give it a try here, the reason we're not using .indexOf() here is lack of support in IE, otherwise it'd be even simpler like this:
function NoneEmpty(arr) {
return arr.indexOf("") === -1;
}
But alas, IE doesn't support this function on arrays, at least not yet.
You have to check in through loop.
function checkArray(my_arr){
for(var i=0;i<my_arr.length;i++){
if(my_arr[i] === "")
return false;
}
return true;
}
You can try jQuery.inArray() function:
return jQuery.inArray("", my_arr)
Using a "higher order function" like filter instead of looping can sometimes make for faster, safer, and more readable code. Here, you could filter the array to remove items that are not the empty string, then check the length of the resultant array.
Basic JavaScript
var my_arr = ["", "hi", ""]
// only keep items that are the empty string
new_arr = my_arr.filter(function(item) {
return item === ""
})
// if filtered array is not empty, there are empty strings
console.log(new_arr);
console.log(new_arr.length === 0);
Modern Javascript: One-liner
var my_arr = ["", "hi", ""]
var result = my_arr.filter(item => item === "").length === 0
console.log(result);
A note about performance
Looping is likely faster in this case, since you can stop looping as soon as you find an empty string. I might still choose to use filter for code succinctness and readability, but either strategy is defensible.
If you needed to loop over all the elements in the array, however-- perhaps to check if every item is the empty string-- filter would likely be much faster than a for loop!
Nowadays we can use Array.includes
my_arr.includes("")
Returns a Boolean
You could do a simple help method for this:
function hasEmptyValues(ary) {
var l = ary.length,
i = 0;
for (i = 0; i < l; i += 1) {
if (!ary[i]) {
return false;
}
}
return true;
}
//check for empty
var isEmpty = hasEmptyValues(myArray);
EDIT: This checks for false, undefined, NaN, null, "" and 0.
EDIT2: Misread the true/false expectation.
..fredrik
function containsEmpty(a) {
return [].concat(a).sort().reverse().pop() === "";
}
alert(containsEmpty(['1','','qwerty','100'])); // true
alert(containsEmpty(['1','2','qwerty','100'])); // false
my_arr.includes("")
This returned undefined instead of a boolean value so here's an alternative.
function checkEmptyString(item){
if (item.trim().length > 0) return false;
else return true;
};
function checkIfArrayContainsEmptyString(array) {
const containsEmptyString = array.some(checkEmptyString);
return containsEmptyString;
};
console.log(checkIfArrayContainsEmptyString(["","hey","","this","is","my","solution"]))
// *returns true*
console.log(checkIfArrayContainsEmptyString(["yay","it","works"]))
// *returns false*
yourArray.join('').length > 0
Join your array without any space in between and check for its length. If the length, turns out to be greater than zero that means array was not empty. If length is less than or equal to zero, then array was empty.
I see in your comments beneath the question that the code example you give is PHP, so I was wondering if you were actually going for the PHP one? In PHP it would be:
function hasEmpty($array)
{
foreach($array as $bit)
{
if(empty($bit)) return true;
}
return false;
}
Otherwise if you actually did need JavaScript, I refer to Nick Craver's answer
Just do a len(my_arr[i]) == 0; inside a loop to check if string is empty or not.
var containsEmpty = !my_arr.some(function(e){return (!e || 0 === e.length);});
This checks for 0, false, undefined, "" and NaN.
It's also a one liner and works for IE 9 and greater.
One line solution to check if string have empty element
let emptyStrings = strArray.filter(str => str.trim().length <= 0);
let strArray = ['str1', '', 'str2', ' ', 'str3', ' ']
let emptyStrings = strArray.filter(str => str.trim().length <= 0);
console.log(emptyStrings)
One line solution to get non-empty strings from an array
let nonEmptyStrings = strArray.filter(str => str.trim().length > 0);
let strArray = ['str1', '', 'str2', ' ', 'str3', ' ']
let nonEmptyStrings = strArray.filter(str => str.trim().length > 0);
console.log(nonEmptyStrings)
If you only care about empty strings then this will do it:
const arr = ["hi","hello","","jj"]
('' in arr) //returns false
the last line checks if an empty string was found in the array.
I don't know if this is the most performant way, but here's a one liner in ES2015+:
// true if not empty strings
// false if there are empty strings
my_arr.filter(x => x).length === my_arr.length
The .filter(x => x) will return all the elements of the array that are not empty nor undefined. You then compare the length of the original array. If they are different, that means that the array contains empty strings.
You have to check in through the array of some functions.
if isEmptyValue is true that means the array has an empty string otherwise not.
const arr=['A','B','','D'];
const isEmptyValue = arr.some(item => item.trim() === '');
console.log(isEmptyValue)
array.includes("") works just fine.
Let a = ["content1", "" , "content2"];
console.log(a.includes(""));
//Output in console
true

Categories

Resources