Test if object with attribute exists in an array using jQuery - javascript

Can someone please tell me the best way to check if an object within an array of objects has a type of 11?
Below is what I have but it will alert for every object in the array, can I check the whole array and get it to alert just the once at the end?
I've seen methods like grep but I've been trying and can't get it to work. I'm using jQuery.
var x;
for (x = 0; x < objects.length; x++) {
if (objects[x].type == 11) {
alert("exists");
} else {
alert("doesnt exist");
}
}

Best way is use Array.some:
var exists = objects.some(function(el) { return el.type === 11 });
In the link there is also a shim for the browser that doesn't support it.
Otherwise you can just iterate:
var exists = false;
for (var i = 0, el; !exists && (el = objects[i++]);)
exists = el.type === 11;
Once you have the exists variable set, you can just do:
if (exists) {
// do something
}
Outside the loop, in both cases.

Your code should actually do it. If you're bothered that the loop will continue uselessly, you can abort it by calling break;
if(objects[x].type == 11){
alert("exists");
break;
}

Make it a function:
function hasObjWithType11(arr) {
var x;
for (x = 0; x < arr.length; x++) {
if(arr[x].type == 11){
return true;
}
}
return false;
}
alert(hasObjWithType11([{type:1}, {type:11}]); // alerts true

This will do it
var exists = false;
for (var x = 0; x < objects.length; x++) {
if(objects[x].type == 11){
exists = true;
break;
}
}
if(exists){
alert("exists");
}

You could make the searching code more reusable by wrapping it into a separate function. That way you can externalize the condition for easier reading:
function array_contains(a, fn)
{
for (i = 0, len = a.length; i < len; ++i) {
if (fn(a[i])) {
return true;
}
}
return false;
}
if (array_contains(objects, function(item) { return item.type == 11; })) {
alert('found');
}
You could also use Array.some():
if (objects.some(function(item) {
return item.type == 11;
})) {
alert('exists');
}
For IE < 9, refer to the MDN documentation for a mock version.

Related

Check if is vowel or consonant

i just want to develop my thinking logic in pure js. The problem is that when i run the script in the console with the help node.js, it shows me for each iteration. Vowel and consonants. But i just need to write in console only once. Maybe, i should save result in a separate variable after the entire list of vowels? But i don't how to do, Below is the code:
// problem who i can't do
function letter(arg) {
var vowel = "aeouiAEOUI";
var result = "";
for(var i = 0; i < vowel.length; i++) {
if(arg === vowel[i]) {
console.log("vowel");
} else {
console.log("consonant");
}
}
}
i found resolved task on the Stack Overflow. But i don't understand why ? arg >= 0 ?
function letter_indexof(arg) {
var vowels = ["a","e","i","o","u"];
if(vowels.indexOf(arg.toLowerCase()) >= 0) {
console.log("vowel");
} else {
console.log("consonant");
}
}
i will be grateful to all for help.
To tweak your current code, you can have a variable which indicates whether the character is a consonant, and starts out as true, and if you find a vowel, reassign it to false, then check that variable:
function letter(arg) {
var vowel = "aeouiAEOUI";
var result = "";
let isConsonant = true;
for (var i = 0; i < vowel.length; i++) {
if (arg === vowel[i]) {
isConsonant = false;
}
}
if (isConsonant) {
console.log("consonant");
} else {
console.log("vowel");
}
}
letter('a');
letter('f');
You could also log and return immediately when finding a vowel:
function letter(arg) {
var vowel = "aeouiAEOUI";
var result = "";
for (var i = 0; i < vowel.length; i++) {
if (arg === vowel[i]) {
console.log("vowel");
return;
}
}
console.log("consonant");
}
letter('a');
letter('f');
It would be easier to use a regular expression, though:
const letter = arg => console.log(
/[aeiou]/i.test(arg) ? 'vowel' : 'consonant'
);
letter('a');
letter('f');

Parameter returns undefined

I am trying to write a function that identifies if a word is an isogram or not. This is what I have done so far:
function isIsogram(word) {
var result;
var counter = 0;
var dubs = 0;
if (word.length === 0) {
result = false;
} else {
var lower = word.toLowerCase();
var array = Array.from(lower);
for (i = 0; i < array.length; i++) {
counter++;
for (j = i + 1; j < array.length; j++) {
if (array[i] === array[j]) {
dubs++;
}
}
}
if ((counter > 0) && (dubs === 0)) {
result = true;
} else if ((counter > 0) && (dubs > 0)) {
result = false;
}
}
console.log(result);
return result;
}
isIsogram("word");
When I run the above code in my browser's javascript console, it works pretty well. But when I post it onto the environment where I am being tested, it gives an error that "word" (the parameter) is undefined.
I even tried hard coding a parameter by declaring a string value for word outside the function, it still said undefined. What am i not doing right?
Seems to work as far as I can see.
Can you provide information about how you call your function isIsogramm('teststring');?
https://jsfiddle.net/TobiObeck/z15eos81/

recursion not working without declaring global variable

Why does version A work but version B doesn't? How can I make version B work without declaring a global variable outside the function (which is bad practice)?
I'm not clear on why I can't just declare count inside the function itself.
A)
var count = 0;
var containsFiveOrMoreDivs = function(domElement) {
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
} else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (containsFiveOrMoreDivs(children[i])) {
return true;
}
}
}
return false;
}
};
B)
var containsFiveOrMoreDivs = function(domElement) {
var count = 0;
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
} else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (containsFiveOrMoreDivs(children[i])) {
return true;
}
}
}
return false;
}
};
What you really need is two functions, one inside the other:
function containsFiveOrMoreDivs(domElement) {
var count = 0;
function doCount(domElement) {
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
}
else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (doCount(children[i])) {
return true;
}
}
}
return false;
}
}
return doCount(domElement);
}
In that setup, you pass in an element reference, and then the outer function calls the inner function after initializing the counter.
original not very good answer here
Your second version ("B") has "count" as a local variable of the function. Each invocation of the function gets its very own "count" variable, and in each invocation the first thing that happens is that it's initialized to zero.
If you don't want a global, you can use a closure:
var containsFiveOrMoreDivs = function() {
var count = 0;
return function(domElement) {
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
} else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (containsFiveOrMoreDivs(children[i])) {
return true;
}
}
}
return false;
}
};
}();
That code wraps your actual counter function in an anonymous function that includes the "count" variable. It won't be global; it'll be completely private to the "containsFiveOrMoreDivs" function. This is like the best of both worlds: you get to treat "count" as a global, but it's not global. You don't need to worry about carrying a parameter around either.
Variables in Javascript exist in function scope. Every time you call containsFiveOrMoreDivs, count will always be 0 in your version B. Hence, infinite recursion.
What you can do, however, is pass in 'count' each time you call from within the function, and use that (ensuring it's initialised correctly the first time):
var containsFiveOrMoreDivs = function(domElement, count) {
if (!count) {
count=0;
}
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
} else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (containsFiveOrMoreDivs(children[i], count)) {
return true;
}
}
}
return false;
}
};
Call it just like you currently are (containsFiveOrMoreDivs('elementname');)
Version B will not work because each time the function is called the counter is redeclared, so counter never increments.
Your recursive function needs to consume count as an argument. The way you have it will initialize count to 0 no matter how many times you recurse.
Here's an example of a recursive function that consumes "the number of times to do something" as a parameter. Modify it to support your case. Your base case would be something like "count is greater than 5", and each time you call recursively, you add 1 to the count you provide to the recursive call.
function executeMany(fn, count) {
if (count > 0) {
fn();
executeMany(fn, count - 1)
}
}
// this logs "Test" to the console twice
executeMany(function() { console.log("Test"); }, 2);
You could define the function with a count parameter and pass an initial value or if you are using a ECMA 16 you could set a default value for the parameter by doing count=0.
var containsFiveOrMoreDivs = function(domElement, count) {
if (domElement && domElement.tagName === "DIV") {
count++;
}
//base case:
if (count >= 5) {
return true;
} else {
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (containsFiveOrMoreDivs(children[i]), count) {
return true;
}
}
}
return false;
}
};
// call function and set counter to some initial value, such as zero
containsFiveOrMoreDivs(domElement, 0);

refactoring working recursion code (hasFiveDIVs) for traversing the DOM

#oriol provided an amazing two line recursive solution for a problem I was working on today.
function numOccurencesRecursive(arr, val) {
if (!arr.length) return 0;
return (arr[0] === val ? 1 : 0) + numOccurencesRecursive(arr.slice(1), val);
}
I was inspired to refactor some spagetti-ish code that I wrote yesterday:
//returns a boolean
function containsFiveOrMoreDivs(domElement) {
var count = 0;
function doCount(domElement) {
if (domElement && domElement.tagName === "DIV") {
count++;
}
if (count >= 5) {
return true;
}
if (domElement.hasChildNodes()) {
var children = domElement.childNodes;
for (var i = 0; i < children.length; i++) {
if (doCount(children[i])) {
return true
}
};
};
return false;
}
return doCount(domElement)
}
containsFiveOrMoreDivs(document);
Here's the attempt:
function containsFiveOrMoreDivsPureRecursion(domElement) {
if (!domElement && domElement.tagName !== "DIV") {
return 0;
}
return (domElement.tagName === "DIV" ? 1 : 0) + containsFiveOrMoreDivsPureRecursion(domElement.childNodes()); //?
}
how would I loop through all the child nodes recursively in this version? Is what I'm doing possible?
With recursion, you should remember to return 1 type of value, however you want to return a boolean yet you want your function to return count too. This really complicates things.
Heres a recursive function to count the element types
function countElements(domElement, elementType) {
count = (domElement && domElement.tagName === elementType.toUpperCase());
if (domElement.hasChildNodes()) {
for (var i = 0; i < domElement.childNodes.length; i++) {
count += countElements(domElement.childNodes[i], elementType);
};
};
return count;
}
you can use it like this to achieve what you want.
countElements(document, 'div') >= 5
However, this might not be the most efficient way of doing it since it will traverse the whole DOM tree but what you really want is for it to stop when you've hit 5 elements.
function containsFiveOrMoreDivsPureRecursion(domElement, elementType) {
var count = 0;
function countElements(domElement, elementType) {
count += (domElement && domElement.tagName === elementType.toUpperCase());
if (count >= 5) return count;
if (domElement.hasChildNodes()) {
for (var i = 0; i < domElement.childNodes.length; i++) {
countElements(domElement.childNodes[i], elementType);
};
};
return count;
}
return countElements(domElement, elementType) >= 5;
}
In this example, you will need to keep a variable outside of your function (thus it's not really a pure recursion) to keep track of the count and be able to return a boolean.

Matching contents of 2 arrays angularjs

I have 2 arrays of the following contents:
var answer = [[2,1],[1,1],[0,0]];
var selectedObject = [[1,1],[0,0],[2,1]];
I want to match the contents of both the arrays. _.Equals is not working for me in the above condition. As the contents being same are not in same position in array.
Is there any easy way to match the contents of above mentioned arrays.
Any demo code, example, or logic will be helpful.
try this way
var baz = [];
angular.forEach(answer, function(key) {
if (-1 === selectedObject.indexOf(key)) {
baz.push(key);
}
});
if(baz.length==0)
{
//Not matched
}
else
{
//matched
}
I don't know about angularjs. But basic logic goes like this,
j=0
for(i=0; i<arr_len; i++){
if(arr1[i] == arr2[i]{
j++;
}
}
if(arr_len == j){
arrays are equal.
}
Finally solved it. Using _.Equals and basic for loop. It was so simple.
if(answerArray.length != selectedAnsArray.length)
{
//wrong answer
return;
}
else
{
for(var x = 0; x < answerArray.length; x++)
{
for(var y = 0; y < selectedAnsArray.length; y++)
{
if(_.isEqual(answerArray[x],selectedAnsArray[y]))
count++;
}
}
if(count==answerArray.length)
{
//correct answer
return;
}
else
{
//wrong answer
return;
}
}

Categories